这里使用动画示例代码进行讲解
// 使用长度为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)