All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.oscim.renderer.GLMatrix Maven / Gradle / Ivy

Go to download

OpenGL vector map library written in Java - running on Android, iOS, Desktop and within the browser.

There is a newer version: 0.21.0
Show newest version
/*
 * Copyright 2013 Hannes Janetzek
 * Copyright 2019 schedul-xor
 *
 * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
 *
 * This program is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program. If not, see .
 */
package org.oscim.renderer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import static org.oscim.backend.GLAdapter.gl;

public class GLMatrix {

    static final Logger log = LoggerFactory.getLogger(GLMatrix.class);
    private static final boolean dbg = false;

    private final long pointer;
    private final FloatBuffer buffer;

    private static final String INVALID_INPUT = "Bad Array!";

    public GLMatrix() {
        pointer = alloc();
        buffer = (getBuffer(pointer)).order(ByteOrder.nativeOrder()).asFloatBuffer();
    }

    /**
     * Set the Matrix from float array
     *
     * @param m float array to copy
     */
    public void set(float[] m) {
        if (m == null || m.length != 16)
            throw new IllegalArgumentException(INVALID_INPUT);

        set(pointer, m);
    }

    /**
     * Get the Matrix as float array
     *
     * @param m float array to store Matrix
     */
    public void get(float[] m) {
        if (m == null || m.length != 16)
            throw new IllegalArgumentException(INVALID_INPUT);

        get(pointer, m);
    }

    /**
     * Copy values from mat
     *
     * @param mat Matrix to copy
     */
    public void copy(GLMatrix mat) {
        copy(pointer, mat.pointer);
    }

    /**
     * Project Vector with Matrix
     *
     * @param vec3 Vector to project
     */
    public void prj(float[] vec3) {
        if (vec3 == null || vec3.length < 3)
            throw new IllegalArgumentException(INVALID_INPUT);

        prj(pointer, vec3);
    }

    /**
     * Project Vectors with Matrix
     *
     * @param vec3 Vector to project
     */
    public void prj3D(float[] vec3, int offset, int length) {
        if (vec3 == null || vec3.length / (offset + length) < 1)
            throw new IllegalArgumentException(INVALID_INPUT);

        prj3D(pointer, vec3, offset, length);
    }

    /**
     * Project Vectors with Matrix
     *
     * @param vec2 Vector to project
     */
    public void prj2D(float[] vec2, int offset, int length) {
        if (vec2 == null || offset < 0 || (length + offset) * 2 > vec2.length)
            throw new IllegalArgumentException(INVALID_INPUT);

        prj2D(pointer, vec2, offset, length);
    }

    /**
     * Project Vectors with Matrix
     *
     * @param vec2 Vector to project
     */
    public void prj2D(float[] src, int src_offset, float[] dst, int dst_offset, int length) {
        if (src == null || src_offset < 0 || length + src_offset * 2 > src.length)
            throw new IllegalArgumentException(INVALID_INPUT);

        prj2D2(pointer, src, src_offset, dst, dst_offset, length);
    }

    /**
     * Multiply rhs onto Matrix.
     *
     * @param rhs right hand side
     */
    public void multiplyRhs(GLMatrix rhs) {
        smulrhs(pointer, rhs.pointer);
    }

    /**
     * Use this matrix as rhs, multiply it on lhs and store result.
     *
     * @param lhs right hand side
     */
    public void multiplyLhs(GLMatrix lhs) {
        smullhs(pointer, lhs.pointer);
    }

    /**
     * Multiply rhs onto lhs and store result in Matrix.
     * 

* This matrix MUST be different from lhs and rhs! *

* when combining matrices for vector projection this * has the same effect first as applying rhs then lhs. * * @param lhs left hand side * @param rhs right hand side */ public void multiplyMM(GLMatrix lhs, GLMatrix rhs) { smul(pointer, lhs.pointer, rhs.pointer); } /** * Transpose mat and store result in Matrix * * @param mat to transpose */ public void transposeM(GLMatrix mat) { strans(pointer, mat.pointer); } /** * Set rotation * * @param a angle in degree * @param x around x-axis * @param y around y-axis * @param z around z-axis */ public void setRotation(float a, float x, float y, float z) { setRotation(pointer, a, x, y, z); } /** * Set translation * * @param x along x-axis * @param y along y-axis * @param z along z-axis */ public void setTranslation(float x, float y, float z) { setTranslation(pointer, x, y, z); } /** * Set scale factor * * @param x axis * @param y axis * @param z axis */ public void setScale(float x, float y, float z) { setScale(pointer, x, y, z); } /** * Set translation and x,y scale * * @param tx translate x * @param ty translate y * @param scale factor x,y */ public void setTransScale(float tx, float ty, float scale) { setTransScale(pointer, tx, ty, scale); } /** * Set Matrix with glUniformMatrix * * @param location GL location id */ public void setAsUniform(int location) { gl.uniformMatrix4fv(location, 1, false, buffer); //setAsUniform(pointer, location); } /** * Set single value * * @param pos at position * @param value value to set */ public void setValue(int pos, float value) { setValueAt(pointer, pos, value); } /** * add some offset (similar to glDepthOffset) * * @param delta offset */ public void addDepthOffset(int delta) { addDepthOffset(pointer, delta); } /** * Set identity matrix */ public void setIdentity() { identity(pointer); } /** * Free native object */ @Override public void finalize() { if (pointer != 0) delete(pointer); } private static native long alloc(); private static native void delete(long self); private static native void set(long self, float[] m); private static native void copy(long self, long other); private static native void identity(long self); private static native void get(long self, float[] m); private static native void mul(long self, long lhs_ptr); private static native void smul(long self, long rhs_ptr, long lhs_ptr); private static native void smulrhs(long self, long rhs_ptr); private static native void smullhs(long self, long lhs_ptr); private static native void strans(long self, long rhs_ptr); private static native void prj(long self, float[] vec3); private static native void prj3D(long self, float[] vec3, int start, int cnt); private static native void prj2D(long self, float[] vec2, int start, int cnt); private static native void prj2D2(long self, float[] vec2, int src_offset, float[] dst_vec, int dst_offset, int length); private static native void setRotation(long self, float a, float x, float y, float z); private static native void setScale(long self, float x, float y, float z); private static native void setTranslation(long self, float x, float y, float z); private static native void setTransScale(long self, float tx, float ty, float scale); //private static native void setAsUniform(long self, int handle); private static native void setValueAt(long self, int pos, float value); private static native void addDepthOffset(long self, int delta); private static native ByteBuffer getBuffer(long self); /* Copyright (C) 2007 The Android Open Source Project * * 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. */ /** * Define a projection matrix in terms of six clip planes * * @param m the float array that holds the perspective matrix * @param offset the offset into float array m where the perspective * matrix data is written */ public static void frustumM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far) { if (left == right) { throw new IllegalArgumentException("left == right"); } if (top == bottom) { throw new IllegalArgumentException("top == bottom"); } if (near == far) { throw new IllegalArgumentException("near == far"); } if (near <= 0.0f) { throw new IllegalArgumentException("near <= 0.0f"); } if (far <= 0.0f) { throw new IllegalArgumentException("far <= 0.0f"); } final float r_width = 1.0f / (right - left); final float r_height = 1.0f / (top - bottom); final float r_depth = 1.0f / (near - far); final float x = 2.0f * (near * r_width); final float y = 2.0f * (near * r_height); final float A = (right + left) * r_width; final float B = (top + bottom) * r_height; final float C = (far + near) * r_depth; final float D = 2.0f * (far * near * r_depth); m[offset + 0] = x; m[offset + 5] = y; m[offset + 8] = A; m[offset + 9] = B; m[offset + 10] = C; m[offset + 14] = D; m[offset + 11] = -1.0f; m[offset + 1] = 0.0f; m[offset + 2] = 0.0f; m[offset + 3] = 0.0f; m[offset + 4] = 0.0f; m[offset + 6] = 0.0f; m[offset + 7] = 0.0f; m[offset + 12] = 0.0f; m[offset + 13] = 0.0f; m[offset + 15] = 0.0f; } /** * Inverts a 4 x 4 matrix. * * @param mInv the array that holds the output inverted matrix * @param mInvOffset an offset into mInv where the inverted matrix is * stored. * @param m the input array * @param mOffset an offset into m where the matrix is stored. * @return true if the matrix could be inverted, false if it could not. */ public static boolean invertM(float[] mInv, int mInvOffset, float[] m, int mOffset) { // Invert a 4 x 4 matrix using Cramer's Rule // transpose matrix final float src0 = m[mOffset + 0]; final float src4 = m[mOffset + 1]; final float src8 = m[mOffset + 2]; final float src12 = m[mOffset + 3]; final float src1 = m[mOffset + 4]; final float src5 = m[mOffset + 5]; final float src9 = m[mOffset + 6]; final float src13 = m[mOffset + 7]; final float src2 = m[mOffset + 8]; final float src6 = m[mOffset + 9]; final float src10 = m[mOffset + 10]; final float src14 = m[mOffset + 11]; final float src3 = m[mOffset + 12]; final float src7 = m[mOffset + 13]; final float src11 = m[mOffset + 14]; final float src15 = m[mOffset + 15]; // calculate pairs for first 8 elements (cofactors) final float atmp0 = src10 * src15; final float atmp1 = src11 * src14; final float atmp2 = src9 * src15; final float atmp3 = src11 * src13; final float atmp4 = src9 * src14; final float atmp5 = src10 * src13; final float atmp6 = src8 * src15; final float atmp7 = src11 * src12; final float atmp8 = src8 * src14; final float atmp9 = src10 * src12; final float atmp10 = src8 * src13; final float atmp11 = src9 * src12; // calculate first 8 elements (cofactors) final float dst0 = (atmp0 * src5 + atmp3 * src6 + atmp4 * src7) - (atmp1 * src5 + atmp2 * src6 + atmp5 * src7); final float dst1 = (atmp1 * src4 + atmp6 * src6 + atmp9 * src7) - (atmp0 * src4 + atmp7 * src6 + atmp8 * src7); final float dst2 = (atmp2 * src4 + atmp7 * src5 + atmp10 * src7) - (atmp3 * src4 + atmp6 * src5 + atmp11 * src7); final float dst3 = (atmp5 * src4 + atmp8 * src5 + atmp11 * src6) - (atmp4 * src4 + atmp9 * src5 + atmp10 * src6); final float dst4 = (atmp1 * src1 + atmp2 * src2 + atmp5 * src3) - (atmp0 * src1 + atmp3 * src2 + atmp4 * src3); final float dst5 = (atmp0 * src0 + atmp7 * src2 + atmp8 * src3) - (atmp1 * src0 + atmp6 * src2 + atmp9 * src3); final float dst6 = (atmp3 * src0 + atmp6 * src1 + atmp11 * src3) - (atmp2 * src0 + atmp7 * src1 + atmp10 * src3); final float dst7 = (atmp4 * src0 + atmp9 * src1 + atmp10 * src2) - (atmp5 * src0 + atmp8 * src1 + atmp11 * src2); // calculate pairs for second 8 elements (cofactors) final float btmp0 = src2 * src7; final float btmp1 = src3 * src6; final float btmp2 = src1 * src7; final float btmp3 = src3 * src5; final float btmp4 = src1 * src6; final float btmp5 = src2 * src5; final float btmp6 = src0 * src7; final float btmp7 = src3 * src4; final float btmp8 = src0 * src6; final float btmp9 = src2 * src4; final float btmp10 = src0 * src5; final float btmp11 = src1 * src4; // calculate second 8 elements (cofactors) final float dst8 = (btmp0 * src13 + btmp3 * src14 + btmp4 * src15) - (btmp1 * src13 + btmp2 * src14 + btmp5 * src15); final float dst9 = (btmp1 * src12 + btmp6 * src14 + btmp9 * src15) - (btmp0 * src12 + btmp7 * src14 + btmp8 * src15); final float dst10 = (btmp2 * src12 + btmp7 * src13 + btmp10 * src15) - (btmp3 * src12 + btmp6 * src13 + btmp11 * src15); final float dst11 = (btmp5 * src12 + btmp8 * src13 + btmp11 * src14) - (btmp4 * src12 + btmp9 * src13 + btmp10 * src14); final float dst12 = (btmp2 * src10 + btmp5 * src11 + btmp1 * src9) - (btmp4 * src11 + btmp0 * src9 + btmp3 * src10); final float dst13 = (btmp8 * src11 + btmp0 * src8 + btmp7 * src10) - (btmp6 * src10 + btmp9 * src11 + btmp1 * src8); final float dst14 = (btmp6 * src9 + btmp11 * src11 + btmp3 * src8) - (btmp10 * src11 + btmp2 * src8 + btmp7 * src9); final float dst15 = (btmp10 * src10 + btmp4 * src8 + btmp9 * src9) - (btmp8 * src9 + btmp11 * src10 + btmp5 * src8); // calculate determinant final float det = src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3; if (det == 0.0f) { return false; } // calculate matrix inverse final float invdet = 1.0f / det; mInv[mInvOffset] = dst0 * invdet; mInv[1 + mInvOffset] = dst1 * invdet; mInv[2 + mInvOffset] = dst2 * invdet; mInv[3 + mInvOffset] = dst3 * invdet; mInv[4 + mInvOffset] = dst4 * invdet; mInv[5 + mInvOffset] = dst5 * invdet; mInv[6 + mInvOffset] = dst6 * invdet; mInv[7 + mInvOffset] = dst7 * invdet; mInv[8 + mInvOffset] = dst8 * invdet; mInv[9 + mInvOffset] = dst9 * invdet; mInv[10 + mInvOffset] = dst10 * invdet; mInv[11 + mInvOffset] = dst11 * invdet; mInv[12 + mInvOffset] = dst12 * invdet; mInv[13 + mInvOffset] = dst13 * invdet; mInv[14 + mInvOffset] = dst14 * invdet; mInv[15 + mInvOffset] = dst15 * invdet; return true; } public static void lookAt(float[] m, int offset, float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz) { float z0 = eyex - centerx; float z1 = eyey - centery; float z2 = eyez - centerz; double len = 1.0 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); z0 *= len; z1 *= len; z2 *= len; float x0 = upy * z2 - upz * z1; float x1 = upz * z0 - upx * z2; float x2 = upx * z1 - upy * z0; len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); if (len == 0) { x0 = x1 = x2 = 0; } else { len = 1.0 / len; x0 *= len; x1 *= len; x2 *= len; } float y0 = z1 * x2 - z2 * x1; float y1 = z2 * x0 - z0 * x2; float y2 = z0 * x1 - z1 * x0; len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); if (len == 0) { y0 = y1 = y2 = 0; } else { len = 1.0 / len; y0 *= len; y1 *= len; y2 *= len; } m[offset + 0] = x0; m[offset + 1] = y0; m[offset + 2] = z0; m[offset + 3] = 0.0f; m[offset + 4] = x1; m[offset + 5] = y1; m[offset + 6] = z1; m[offset + 7] = 0.0f; m[offset + 8] = x2; m[offset + 9] = y2; m[offset + 10] = z2; m[offset + 11] = 0.0f; m[offset + 12] = -(x0 * eyex + x1 * eyey + x2 * eyez); m[offset + 13] = -(y0 * eyex + y1 * eyey + y2 * eyez); m[offset + 14] = -(z0 * eyex + z1 * eyey + z2 * eyez); m[offset + 15] = 1.0f; } public static void orthoM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far) { final float r_width = 1.0f / (left - right); final float r_height = 1.0f / (bottom - top); final float r_depth = 1.0f / (near - far); m[offset + 0] = -2.0f * r_width; m[offset + 5] = -2.0f * r_height; m[offset + 10] = 2.0f * r_depth; m[offset + 12] = (left + right) * r_width; m[offset + 13] = (top + bottom) * r_height; m[offset + 14] = (far + near) * r_depth; m[offset + 1] = 0.0f; m[offset + 2] = 0.0f; m[offset + 3] = 0.0f; m[offset + 4] = 0.0f; m[offset + 6] = 0.0f; m[offset + 7] = 0.0f; m[offset + 8] = 0.0f; m[offset + 9] = 0.0f; m[offset + 11] = 0.0f; m[offset + 15] = 1.0f; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy