From 8c1628680fe33a2972753b9d3bb1f97e9b35bfc3 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Tue, 27 Nov 2018 22:43:28 +0100 Subject: [PATCH] Added support for texture coordinates and optionals vertex normals --- orx-obj-loader/src/main/kotlin/OBJLoader.kt | 46 +++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/orx-obj-loader/src/main/kotlin/OBJLoader.kt b/orx-obj-loader/src/main/kotlin/OBJLoader.kt index ab59d452..53e70e89 100644 --- a/orx-obj-loader/src/main/kotlin/OBJLoader.kt +++ b/orx-obj-loader/src/main/kotlin/OBJLoader.kt @@ -10,9 +10,11 @@ import java.io.File import java.net.MalformedURLException import java.net.URL -class Triangle(val positions: Array, val normals: Array) { +class Triangle(val positions: Array = emptyArray(), + val normals: Array = emptyArray(), + val textureCoords: Array = emptyArray()) { fun transform(t: Matrix44): Triangle { - return Triangle(positions.map { (t * it.xyz1).div }.toTypedArray(), normals) + return Triangle(positions.map { (t * it.xyz1).div }.toTypedArray(), normals, textureCoords) } } @@ -92,8 +94,18 @@ fun loadOBJasVertexBuffer(lines: List): VertexBuffer { it.value.forEach { for (i in 0 until it.positions.size) { write(it.positions[i]) - write(it.normals[i]) - write(Vector2.ZERO) + if (it.normals.size > 0) { + write(it.normals[i]) + } else { + val d0 = it.positions[2] - it.positions[0] + val d1 = it.positions[1] - it.positions[0] + write(d0.normalized.cross(d1.normalized).normalized) + } + if (it.textureCoords.size > 0) { + write(it.textureCoords[i]) + } else { + write(Vector2.ZERO) + } } } } @@ -110,6 +122,7 @@ fun loadOBJ(lines: List): Map> { val meshes = mutableMapOf>() val positions = mutableListOf() val normals = mutableListOf() + val textureCoords = mutableListOf() var activeMesh = mutableListOf() lines.forEach { line -> @@ -122,6 +135,7 @@ fun loadOBJ(lines: List): Map> { positions += Vector3(tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble()) } "vn" -> normals += Vector3(tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble()) + "vt" -> textureCoords += Vector2(tokens[1].toDouble(), tokens[2].toDouble()) "g" -> { activeMesh = mutableListOf() meshes[tokens[1]] = activeMesh @@ -132,17 +146,35 @@ fun loadOBJ(lines: List): Map> { } if (indices.size == 3) { - val ps = arrayOf( + + val attributes = indices[0].size + + val ps = if (attributes >= 1) arrayOf( indices[0][0]?.let { positions[it - 1] } ?: Vector3.ZERO, indices[1][0]?.let { positions[it - 1] } ?: Vector3.ZERO, indices[2][0]?.let { positions[it - 1] } ?: Vector3.ZERO) + else + emptyArray() - val ns = arrayOf( + val tcs = if (attributes >= 2) arrayOf( + indices[0][1]?.let { textureCoords[it - 1] } ?: Vector2.ZERO, + indices[1][1]?.let { textureCoords[it - 1] } ?: Vector2.ZERO, + indices[2][1]?.let { textureCoords[it - 1] } ?: Vector2.ZERO) + else + emptyArray() + + + val ns = if (attributes >= 3) arrayOf( indices[0][2]?.let { normals[it - 1] } ?: Vector3.ZERO, indices[1][2]?.let { normals[it - 1] } ?: Vector3.ZERO, indices[2][2]?.let { normals[it - 1] } ?: Vector3.ZERO) + else + emptyArray() - activeMesh.add(Triangle(ps, ns)) + activeMesh.add(Triangle(ps, ns, tcs)) + if(meshes.isEmpty()) { + meshes["no-name"] = activeMesh + } } else { TODO("implement non triangular surfaces ${indices.size}") }