Added orx-obj-loader

This commit is contained in:
edwin
2018-11-23 14:38:12 +01:00
parent a25a1c5da1
commit 6e6cfe0d4c
5 changed files with 202 additions and 42 deletions

View File

@@ -1,39 +1,40 @@
# ORX (OPENRNDR EXTRA) # ORX (OPENRNDR EXTRA)
[![](https://jitpack.io/v/openrndr/orx.svg)](https://jitpack.io/#openrndr/orx) [![](https://jitpack.io/v/openrndr/orx.svg)](https://jitpack.io/#openrndr/orx)
A growing library of assorted data structures, algorithms and utilities. A growing library of assorted data structures, algorithms and utilities.
- [`orx-compositor`](orx-compositor/README.md), a simple toolkit to make composite (layered) images - [`orx-compositor`](orx-compositor/README.md), a simple toolkit to make composite (layered) images
- [`orx-filter-extension`](orx-filter-extension/README.md), Program extension method that provides Filter based `extend()` - [`orx-filter-extension`](orx-filter-extension/README.md), Program extension method that provides Filter based `extend()`
- [`orx-integral-image`](orx-integral-image/README.md), a CPU-based implementation for integral images (summed area tables) - [`orx-integral-image`](orx-integral-image/README.md), a CPU-based implementation for integral images (summed area tables)
- `orx-jumpflood`, a filter/shader based implementation of the jump flood algorithm for finding fast approximate (directional) distance fields - `orx-jumpflood`, a filter/shader based implementation of the jump flood algorithm for finding fast approximate (directional) distance fields
- `orx-kdtree`, a kd-tree implementation for fast nearest point searches - `orx-kdtree`, a kd-tree implementation for fast nearest point searches
- [`orx-mesh-generators`](orx-mesh-generators/README.md), triangular mesh generators - [`orx-mesh-generators`](orx-mesh-generators/README.md), triangular mesh generators
- [`orx-no-clear`](orx-no-clear/README.md), a simple extension that provides drawing without clearing the background - [`orx-no-clear`](orx-no-clear/README.md), a simple extension that provides drawing without clearing the background
- [`orx-obj-loader`](orx-obj-loader/README.md), simple Wavefront .obj mesh loader
## Usage
ORX 0.0.13 is built against OPENRNDR 0.3.29, make sure you use this version in your project. Because OPENRNDR's API is pre 1.0 it tends to change from time to time. ## Usage
ORX 0.0.14 is built against OPENRNDR 0.3.30-rc1, make sure you use this version in your project. Because OPENRNDR's API is pre 1.0 it tends to change from time to time.
The easiest way to add ORX to your project is through the use of Jitpack. [Jitpack](http://jitpack.io) is a service that pulls Gradle based libraries from Github, builds them and serves the jar files.
The easiest way to add ORX to your project is through the use of Jitpack. [Jitpack](http://jitpack.io) is a service that pulls Gradle based libraries from Github, builds them and serves the jar files.
To setup Jitpack support in your project all you have to do is add the Jitpack repository to your `repositories {}`. It is advised to have the jitpack repository as the last entry.
``` To setup Jitpack support in your project all you have to do is add the Jitpack repository to your `repositories {}`. It is advised to have the jitpack repository as the last entry.
repositories { ```
maven { url 'https://jitpack.io' } repositories {
} maven { url 'https://jitpack.io' }
``` }
```
You can then add any of the ORX artefacts to your `dependencies {}`:
``` You can then add any of the ORX artefacts to your `dependencies {}`:
dependencies { ```
compile 'com.github.openrndr.orx:<orx-artifact>:v0.0.13' dependencies {
} compile 'com.github.openrndr.orx:<orx-artifact>:v0.0.14'
``` }
```
For example if you want to use the `orx-no-clear` artifact one would use:
``` For example if you want to use the `orx-no-clear` artifact one would use:
dependencies { ```
compile 'com.github.openrndr.orx:orx-no-clear:v0.0.13' dependencies {
} compile 'com.github.openrndr.orx:orx-no-clear:v0.0.14'
``` }
```

View File

@@ -4,7 +4,7 @@ plugins {
allprojects { allprojects {
group 'org.openrndr.extra' group 'org.openrndr.extra'
version '0.0.13' version '0.0.14'
} }
repositories { repositories {
@@ -13,7 +13,7 @@ repositories {
} }
ext { ext {
openrndrVersion = "0.3.29" openrndrVersion = "0.3.30-rc1"
} }
subprojects { subprojects {

18
orx-obj-loader/README.md Normal file
View File

@@ -0,0 +1,18 @@
# orx-obj-loader
A simple loader for Wavefront .obj files
##### Usage
Loading directly into a vertex buffer can be done through `loadOBJasVertexBuffer`.
```kotlin
val vertexBuffer = loadOBJasVertexBuffer("data/someObject.obj")
```
The loaded vertex buffer can be drawn like this:
```kotlin
drawer.vertexBuffer(vertexBuffer, DrawPrimitive.TRIANGLES)
```

View File

@@ -0,0 +1,140 @@
package modeling
import org.openrndr.draw.VertexBuffer
import org.openrndr.draw.vertexBuffer
import org.openrndr.draw.vertexFormat
import org.openrndr.math.Matrix44
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import java.io.File
import java.net.MalformedURLException
import java.net.URL
class Triangle(val positions: Array<Vector3>, val normals: Array<Vector3>) {
fun transform(t: Matrix44): Triangle {
return Triangle(positions.map { (t * it.xyz1).div }.toTypedArray(), normals)
}
}
class Box(val corner: Vector3, val width: Double, val height: Double, val depth: Double)
fun bounds(triangles: List<Triangle>): Box {
var minX = Double.POSITIVE_INFINITY
var minY = Double.POSITIVE_INFINITY
var minZ = Double.POSITIVE_INFINITY
var maxX = Double.NEGATIVE_INFINITY
var maxY = Double.NEGATIVE_INFINITY
var maxZ = Double.NEGATIVE_INFINITY
triangles.forEach {
it.positions.forEach {
minX = Math.min(minX, it.x)
minY = Math.min(minY, it.y)
minZ = Math.min(minZ, it.z)
maxX = Math.max(maxX, it.x)
maxY = Math.max(maxY, it.y)
maxZ = Math.max(maxZ, it.z)
}
}
return Box(Vector3(minX, minY, minZ), maxX - minX, maxY - minY, maxZ - minZ)
}
fun loadOBJ(fileOrUrl: String): Map<String, List<Triangle>> {
return try {
val url = URL(fileOrUrl)
loadOBJ(url)
} catch (e: MalformedURLException) {
loadOBJ(File(fileOrUrl))
}
}
private val objVertexFormat = vertexFormat {
position(3)
normal(3)
textureCoordinate(2)
}
fun loadOBJasVertexBuffer(fileOrUrl: String): VertexBuffer {
return try {
val url = URL(fileOrUrl)
loadOBJasVertexBuffer(url)
} catch (e: MalformedURLException) {
loadOBJasVertexBuffer(File(fileOrUrl))
}
}
fun loadOBJasVertexBuffer(url: URL): VertexBuffer = loadOBJasVertexBuffer(url.readText().split("\n"))
fun loadOBJasVertexBuffer(file: File): VertexBuffer = loadOBJasVertexBuffer(file.readLines())
fun loadOBJasVertexBuffer(lines: List<String>): VertexBuffer {
val objects = loadOBJ(lines)
val triangleCount = objects.values.sumBy { it.size }
val vertexBuffer = vertexBuffer(objVertexFormat, triangleCount * 3)
vertexBuffer.put {
objects.entries.forEach {
it.value.forEach {
for (i in 0 until it.positions.size) {
write(it.positions[i])
write(it.normals[i])
write(Vector2.ZERO)
}
}
}
}
vertexBuffer.shadow.destroy()
return vertexBuffer
}
fun loadOBJ(file: File): Map<String, List<Triangle>> = loadOBJ(file.readLines())
fun loadOBJ(url: URL): Map<String, List<Triangle>> = loadOBJ(url.readText().split("\n"))
fun loadOBJ(lines: List<String>): Map<String, List<Triangle>> {
val meshes = mutableMapOf<String, List<Triangle>>()
val positions = mutableListOf<Vector3>()
val normals = mutableListOf<Vector3>()
var activeMesh = mutableListOf<Triangle>()
lines.forEach { line ->
if (line.isNotEmpty()) {
val tokens = line.split(Regex("[ |\t]+")).map { it.trim() }.filter { it.isNotEmpty() }
if (tokens.isNotEmpty()) {
when (tokens[0]) {
"v" -> {
positions += Vector3(tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble())
}
"vn" -> normals += Vector3(tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble())
"g" -> {
activeMesh = mutableListOf()
meshes[tokens[1]] = activeMesh
}
"f" -> {
val indices = tokens.subList(1, tokens.size).map { it.split("/") }.map {
it.map { it.toIntOrNull() }
}
if (indices.size == 3) {
val ps = 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)
val ns = 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)
activeMesh.add(Triangle(ps, ns))
} else {
TODO("implement non triangular surfaces ${indices.size}")
}
}
}
}
}
}
return meshes
}

View File

@@ -6,7 +6,8 @@ include 'orx-compositor',
'orx-jumpflood', 'orx-jumpflood',
'orx-kdtree', 'orx-kdtree',
'orx-mesh-generators', 'orx-mesh-generators',
'orx-no-clear' 'orx-no-clear',
'orx-obj-loader'