使用方法

常用类

代码讲解

这里使用动画示例代码进行讲解

矩阵、坐标封装

// 使用长度为4的float数组片段表示一个(x,y,z,w)坐标
class Vec(val data: FloatArray = floatArrayOf(0f, 0f, 0f, 1f), val offset: Int = 0) {
    var x: Float
        get() = data[offset]
        set(value) {
            data[offset] = value
        }

    var y: Float
        get() = data[offset + 1]
        set(value) {
            data[offset + 1] = value
        }

    var z: Float
        get() = data[offset + 2]
        set(value) {
            data[offset + 2] = value
        }

    var w: Float
        get() = data[offset + 3]
        set(value) {
            data[offset + 3] = value
        }
	 
    // 归一化
    fun normalize(): Vec {
        if (w > 1e6 && w < -1e6) {
            x /= w
            y /= w
            z /= w
            w = 1f
        }
        return this
    }

    override fun toString(): String {
        return "vec[$x, $y, $z, $w]"
    }
}

// 使用长度为16的float数组片段表示一个4x4矩阵
class Mat(val data: FloatArray = FloatArray(16) { 0f }, val offset: Int = 0) {
    // 设置为矩阵
    fun asIdentity(): Mat {
        Matrix.setIdentityM(data, offset)
        return this
    }

    // 使用观察者位置、目标位置、与摄像机上方的方向表示一个View Matrix
    fun asLookAt(eyeX: Float, eyeY: Float, eyeZ: Float,
                 centerX: Float, centerY: Float, centerZ: Float,
                 upX: Float = 0f, upY: Float = 1f, upZ: Float = 0f): Mat {
        Matrix.setLookAtM(data, offset, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ)
        return this
    }

    // 使用观察者位置、目标位置、与摄像机上方的方向表示一个View Matrix
    fun asLookAt(eye: Vec, center: Vec, up: Vec = Vec(data = floatArrayOf(0f, 1f, 0f, 1f))): Mat {
        Matrix.setLookAtM(data, offset,
                eye.x, eye.y, eye.z,
                center.x, center.y, center.z,
                up.x, up.y, up.z)
        return this
    }

    // 使用视角大小、宽高比、远近平面距离定义一个透视Projection Matrix
    fun asPerspective(fov: Float, aspect: Float, near: Float, far: Float): Mat {
        Matrix.perspectiveM(data, offset, fov, aspect, near, far)
        return this
    }

    // 使用近平面矩形、远近平面距离定义一个透视Projection Matrix
    fun asFrustum(left: Float, right: Float, bottom: Float, top: Float, near: Float, far: Float): Mat {
        Matrix.frustumM(data, offset, left, right, bottom, top, near, far)
        return this
    }
    
    // 使用近平面矩形、远近平面距离定义一个正交Projection Matrix
    fun asOrtho(left: Float, right: Float, bottom: Float, top: Float, near: Float, far: Float): Mat {
        Matrix.orthoM(data, offset, left, right, bottom, top, near, far)
        return this
    }

    // 乘法,使用此矩阵乘以另一个矩阵
    fun mul(right: Mat, result: Mat = Mat()): Mat {
        Matrix.multiplyMM(result.data, result.offset, data, offset, right.data, right.offset)
        return result
    }

    // 乘法,使用此矩阵乘以另一个向量,可以理解为对向量的变换
    fun mul(right: Vec, result: Vec = Vec()): Vec {
        Matrix.multiplyMV(result.data, result.offset, data, offset, right.data, right.offset)
        return result
    }

    // 平移此矩阵
    fun translate(x: Float = 0f, y: Float = 0f, z: Float = 0f): Mat {
        Matrix.translateM(data, offset, x, y, z)
        return this
    }

    // 旋转此矩阵
    fun rotate(a: Float, x: Float, y: Float, z: Float): Mat {
        Matrix.rotateM(data, offset, a, x, y, z)
        return this
    }

    // 缩放此矩阵
    fun scale(x: Float = 1f, y: Float = 1f, z: Float = 1f): Mat {
        Matrix.scaleM(data, offset, x, y, z)
        return this
    }
}

动画

val mvp = Mat().asPerspective(60f, 1f, 0.1f, 10f) * Mat().asLookAt(0f, 0f, -5f, 0f, 0f, 0f, 0f, 1f, 0f)
val rotate = Mat().asIdentity().rotate(ang, 0f, 1f, 0f)
val finalMvp = mvp * rotate
GLES20.glUniformMatrix4fv(uMvp, 1, false, finalMvp.data, finalMvp.offset)