@@ -10,6 +10,7 @@ import com.dmitrybrant.modelviewer.util.Util.readIntLe
1010import java.io.*
1111import java.nio.ByteBuffer
1212import java.nio.ByteOrder
13+ import java.nio.FloatBuffer
1314
1415/*
1516*
@@ -32,6 +33,16 @@ import java.nio.ByteOrder
3233*/
3334class PlyModel (inputStream : InputStream ) : IndexedModel() {
3435 private val pointColor = floatArrayOf(1.0f , 1.0f , 1.0f )
36+ private var colorBuffer: FloatBuffer ? = null
37+
38+ private var xIndex = - 1
39+ private var yIndex = - 1
40+ private var zIndex = - 1
41+ private var rIndex = - 1
42+ private var gIndex = - 1
43+ private var bIndex = - 1
44+ private var alphaIndex = - 1
45+ private var haveColor = false
3546
3647 init {
3748 val stream = BufferedInputStream (inputStream, INPUT_BUFFER_SIZE )
@@ -46,7 +57,7 @@ class PlyModel(inputStream: InputStream) : IndexedModel() {
4657 GLES20 .glDeleteProgram(glProgram)
4758 glProgram = - 1
4859 }
49- glProgram = compileProgram(R .raw.point_cloud_vertex, R .raw.single_color_fragment , arrayOf(" a_Position" ))
60+ glProgram = compileProgram(R .raw.point_cloud_vertex, R .raw.point_cloud_fragment , arrayOf(" a_Position" , " a_Color " ))
5061 initModelMatrix(boundSize)
5162 }
5263
@@ -62,6 +73,7 @@ class PlyModel(inputStream: InputStream) : IndexedModel() {
6273
6374 private fun readText (stream : BufferedInputStream ) {
6475 val vertices = mutableListOf<Float >()
76+ val colors = mutableListOf<Float >()
6577 val reader = BufferedReader (InputStreamReader (stream), INPUT_BUFFER_SIZE )
6678 var line: String
6779 var lineArr: Array <String >
@@ -74,42 +86,66 @@ class PlyModel(inputStream: InputStream) : IndexedModel() {
7486 */
7587 stream.mark(0x100000 )
7688 var isBinary = false
89+ var propIndex = 0
7790 while (reader.readLine().also { line = it.orEmpty() } != null ) {
7891 line = line.trim()
92+ lineArr = line.split(" " ).toTypedArray()
7993 if (line.startsWith(" format " )) {
8094 if (line.contains(" binary" )) {
8195 isBinary = true
8296 }
8397 } else if (line.startsWith(" element vertex" )) {
84- lineArr = line.split(" " .toRegex()).toTypedArray()
8598 vertexCount = lineArr[2 ].toInt()
99+ } else if (line.startsWith(" property " )) {
100+ val propName = lineArr[lineArr.size - 1 ]
101+ if (propName == " x" && xIndex < 0 ) { xIndex = propIndex }
102+ else if (propName == " y" && yIndex < 0 ) { yIndex = propIndex }
103+ else if (propName == " z" && zIndex < 0 ) { zIndex = propIndex }
104+ else if (propName == " red" && rIndex < 0 ) { rIndex = propIndex }
105+ else if (propName == " green" && gIndex < 0 ) { gIndex = propIndex }
106+ else if (propName == " blue" && bIndex < 0 ) { bIndex = propIndex }
107+ else if (propName == " alpha" && alphaIndex < 0 ) { alphaIndex = propIndex }
108+ propIndex++
86109 } else if (line.startsWith(" end_header" )) {
87110 break
88111 }
89112 }
90113 if (vertexCount <= 0 ) {
91114 return
92115 }
116+ if (rIndex >= 0 && gIndex >= 0 && bIndex >= 0 ) {
117+ haveColor = true
118+ }
93119
94120 if (isBinary) {
95121 stream.reset()
96- readVerticesBinary(vertices, stream)
122+ readVerticesBinary(vertices, colors, stream)
97123 } else {
98- readVerticesText(vertices, reader)
124+ readVerticesText(vertices, colors, reader)
99125 }
100126
101- val floatArray = FloatArray (vertices.size)
127+ var floatArray = FloatArray (vertices.size)
102128 for (i in vertices.indices) {
103129 floatArray[i] = vertices[i]
104130 }
105- val vbb = ByteBuffer .allocateDirect(floatArray.size * BYTES_PER_FLOAT )
131+ var vbb = ByteBuffer .allocateDirect(floatArray.size * BYTES_PER_FLOAT )
106132 vbb.order(ByteOrder .nativeOrder())
107133 vertexBuffer = vbb.asFloatBuffer()
108134 vertexBuffer!! .put(floatArray)
109135 vertexBuffer!! .position(0 )
136+
137+ floatArray = FloatArray (colors.size)
138+ for (i in colors.indices) {
139+ floatArray[i] = colors[i]
140+ }
141+ vbb = ByteBuffer .allocateDirect(floatArray.size * BYTES_PER_FLOAT )
142+ vbb.order(ByteOrder .nativeOrder())
143+ colorBuffer = vbb.asFloatBuffer()
144+ colorBuffer!! .put(floatArray)
145+ colorBuffer!! .position(0 )
110146 }
111147
112- private fun readVerticesText (vertices : MutableList <Float >, reader : BufferedReader ) {
148+ private fun readVerticesText (vertices : MutableList <Float >, colors : MutableList < Float >, reader : BufferedReader ) {
113149 var lineArr: Array <String >
114150 var x: Float
115151 var y: Float
@@ -119,24 +155,35 @@ class PlyModel(inputStream: InputStream) : IndexedModel() {
119155 var centerMassZ = 0.0
120156
121157 for (i in 0 until vertexCount) {
122- lineArr = reader.readLine().trim().split(" " .toRegex() ).toTypedArray()
123- x = lineArr[0 ].toFloat()
124- y = lineArr[1 ].toFloat()
125- z = lineArr[2 ].toFloat()
158+ lineArr = reader.readLine().trim().split(" " ).toTypedArray()
159+ x = lineArr[xIndex ].toFloat()
160+ y = lineArr[yIndex ].toFloat()
161+ z = lineArr[zIndex ].toFloat()
126162 vertices.add(x)
127163 vertices.add(y)
128164 vertices.add(z)
129165 adjustMaxMin(x, y, z)
130166 centerMassX + = x.toDouble()
131167 centerMassY + = y.toDouble()
132168 centerMassZ + = z.toDouble()
169+ if (haveColor) {
170+ colors.add(lineArr[rIndex].toFloat() / 255f )
171+ colors.add(lineArr[gIndex].toFloat() / 255f )
172+ colors.add(lineArr[bIndex].toFloat() / 255f )
173+ colors.add(if (alphaIndex >= 0 ) lineArr[alphaIndex].toFloat() / 255f else 1f )
174+ } else {
175+ colors.add(pointColor[0 ])
176+ colors.add(pointColor[1 ])
177+ colors.add(pointColor[2 ])
178+ colors.add(255f )
179+ }
133180 }
134181 this .centerMassX = (centerMassX / vertexCount).toFloat()
135182 this .centerMassY = (centerMassY / vertexCount).toFloat()
136183 this .centerMassZ = (centerMassZ / vertexCount).toFloat()
137184 }
138185
139- private fun readVerticesBinary (vertices : MutableList <Float >, stream : BufferedInputStream ) {
186+ private fun readVerticesBinary (vertices : MutableList <Float >, colors : MutableList < Float >, stream : BufferedInputStream ) {
140187 val tempBytes = ByteArray (0x1000 )
141188 stream.mark(1 )
142189 stream.read(tempBytes)
@@ -164,6 +211,12 @@ class PlyModel(inputStream: InputStream) : IndexedModel() {
164211 centerMassX + = x.toDouble()
165212 centerMassY + = y.toDouble()
166213 centerMassZ + = z.toDouble()
214+
215+ // TODO: extract color from binary format
216+ colors.add(pointColor[0 ])
217+ colors.add(pointColor[1 ])
218+ colors.add(pointColor[2 ])
219+ colors.add(255f )
167220 }
168221 this .centerMassX = (centerMassX / vertexCount).toFloat()
169222 this .centerMassY = (centerMassY / vertexCount).toFloat()
@@ -177,11 +230,13 @@ class PlyModel(inputStream: InputStream) : IndexedModel() {
177230 GLES20 .glUseProgram(glProgram)
178231 val mvpMatrixHandle = GLES20 .glGetUniformLocation(glProgram, " u_MVP" )
179232 val positionHandle = GLES20 .glGetAttribLocation(glProgram, " a_Position" )
233+ val colorHandle = GLES20 .glGetAttribLocation(glProgram, " a_Color" )
180234 val pointThicknessHandle = GLES20 .glGetUniformLocation(glProgram, " u_PointThickness" )
181235 val ambientColorHandle = GLES20 .glGetUniformLocation(glProgram, " u_ambientColor" )
182236 GLES20 .glEnableVertexAttribArray(positionHandle)
183- GLES20 .glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX , GLES20 .GL_FLOAT , false ,
184- VERTEX_STRIDE , vertexBuffer)
237+ GLES20 .glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX , GLES20 .GL_FLOAT , false , VERTEX_STRIDE , vertexBuffer)
238+ GLES20 .glEnableVertexAttribArray(colorHandle)
239+ GLES20 .glVertexAttribPointer(colorHandle, 4 , GLES20 .GL_FLOAT , false , 4 * BYTES_PER_FLOAT , colorBuffer)
185240 Matrix .multiplyMM(mvMatrix, 0 , viewMatrix, 0 , modelMatrix, 0 )
186241 Matrix .multiplyMM(mvpMatrix, 0 , projectionMatrix, 0 , mvMatrix, 0 )
187242 GLES20 .glUniformMatrix4fv(mvpMatrixHandle, 1 , false , mvpMatrix, 0 )
0 commit comments