Added orx-obj-loader
This commit is contained in:
79
README.md
79
README.md
@@ -1,39 +1,40 @@
|
|||||||
# ORX (OPENRNDR EXTRA)
|
# ORX (OPENRNDR EXTRA)
|
||||||
|
|
||||||
[](https://jitpack.io/#openrndr/orx)
|
[](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'
|
||||||
```
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -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
18
orx-obj-loader/README.md
Normal 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)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
140
orx-obj-loader/src/main/kotlin/OBJLoader.kt
Normal file
140
orx-obj-loader/src/main/kotlin/OBJLoader.kt
Normal 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
|
||||||
|
}
|
||||||
@@ -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'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user