我想在我的Android应用程序中显示3D点数组,即带有OpenGL的顶点。我正在从.obj文件中读取顶点,现在我只想显示这些顶点,即没有面元素等。我将顶点的3D坐标加载到FloatBuffer中,当我调用glDrawElements
方法时,它什么都不显示。有帮助吗?
代码如下:
class PreviewActivity : AppCompatActivity() {
private lateinit var surfaceView : GLSurfaceView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_opengl_preview)
surfaceView = findViewById(R.id.my_surface_view)
surfaceView.setEGLContextClientVersion(3)
surfaceView.setRenderer(renderer)
}
private var model : Model? = null
private val renderer = object : GLSurfaceView.Renderer {
override fun onDrawFrame(gl: GL10?) {
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT)
model?.draw()
}
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
GLES31.glViewport(0, 0, width, height)
}
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
surfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
model = Model(applicationContext)
}
}
}
class Model(context : Context) {
private val verticesList : List<String>
private val verticesBuffer : FloatBuffer
private val program : Int
init {
verticesList = ArrayList()
val filePath = "storage/emulated/0/Pictures/DiplRaw/torus.obj"
val file = File(filePath)
val scanner = Scanner(file)
while (scanner.hasNextLine()) {
val line = scanner.nextLine()
if(line.startsWith("v ")) {
verticesList.add(line)
}
}
scanner.close()
val buffer = ByteBuffer.allocateDirect(verticesList.size * 3 * 4) //3 koordinate po 8 byteova (Double je!)
buffer.order(ByteOrder.nativeOrder())
verticesBuffer = buffer.asFloatBuffer()
for(vertex in verticesList) {
val coords = vertex.split(" ")
val x = coords[1].toFloat()
val y = coords[2].toFloat()
val z = coords[3].toFloat()
verticesBuffer.put(x)
verticesBuffer.put(y)
verticesBuffer.put(z)
}
verticesBuffer.position(0)
val vertexSharedStream = context.resources.openRawResource(R.raw.vertex_shader)
val vertexSharedCode = IOUtils.toString(vertexSharedStream, Charset.defaultCharset())
vertexSharedStream.close()
val fragmentSharedStream = context.resources.openRawResource(R.raw.fragment_shader)
val fragmentSharedCode = IOUtils.toString(fragmentSharedStream, Charset.defaultCharset())
fragmentSharedStream.close()
val vertexShader = GLES31.glCreateShader(GLES31.GL_VERTEX_SHADER)
GLES31.glShaderSource(vertexShader, vertexSharedCode)
val fragmentShader = GLES31.glCreateShader(GLES31.GL_FRAGMENT_SHADER)
GLES31.glShaderSource(fragmentShader, fragmentSharedCode)
GLES31.glCompileShader(vertexShader)
GLES31.glCompileShader(fragmentShader)
program = GLES31.glCreateProgram()
GLES31.glAttachShader(program, vertexShader)
GLES31.glAttachShader(program, fragmentShader)
GLES31.glLinkProgram(program)
GLES31.glUseProgram(program)
}
fun draw() {
val position = GLES31.glGetAttribLocation(program, "position")
GLES31.glEnableVertexAttribArray(position)
GLES31.glVertexAttribPointer(position, 3, GLES31.GL_FLOAT, false, 3*4, verticesBuffer)
val projectionMatrix = FloatArray(16)
val viewMatrix = FloatArray(16)
val productMatrix = FloatArray(16)
Matrix.frustumM(projectionMatrix, 0, -1f, 1f, -1f, 1f, 2f, 9f) //TODO
Matrix.setLookAtM(viewMatrix, 0, 0f, 3f, -4f, 0f, 0f, 0f, 0f, 1f, 0f)
Matrix.multiplyMM(productMatrix, 0, projectionMatrix,0, viewMatrix,0)
val matrix = GLES31.glGetUniformLocation(program, "matrix")
GLES31.glUniformMatrix4fv(matrix, 1, false, productMatrix, 0)
GLES31.glDrawElements(GLES31.GL_POINTS, verticesList.size, GLES31.GL_FLOAT, verticesBuffer)
GLES31.glDisableVertexAttribArray(position)
}
}
这是我的vertex_shader.txt文件:
attribute vec4 position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
gl_PointSize = 10.0;
}
和我的fragment_shader.txt文件:
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0.5, 0, 1.0);
}