More work on 3d

This commit is contained in:
soywiz
2019-03-12 06:55:31 +01:00
parent 24d96c67f0
commit 992de928cc
6 changed files with 294 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
package com.soywiz.korge.experimental.s3d
import com.soywiz.korge.experimental.s3d.model.internal.*
import com.soywiz.korma.geom.*
abstract class Camera3D : View3D() {
@@ -34,6 +35,8 @@ abstract class Camera3D : View3D() {
// Do nothing except when debugging
}
abstract fun clone(): Camera3D
class Perspective(
fov: Angle = 60.degrees,
near: Double = 0.3,
@@ -52,6 +55,10 @@ abstract class Camera3D : View3D() {
override fun updateMatrix(mat: Matrix3D, width: Double, height: Double) {
mat.setToPerspective(fov, if (height != 0.0) width / height else 1.0, near, far)
}
override fun clone(): Perspective = Perspective(fov, near, far).apply {
this.localTransform.copyFrom(this@Perspective.localTransform)
}
}
}
@@ -156,6 +163,19 @@ class Transform3D {
matrixDirty = true
scale.setTo(x, y, z, w)
}
fun copyFrom(localTransform: Transform3D) {
this.setMatrix(localTransform.matrix)
}
fun setToInterpolated(a: Transform3D, b: Transform3D, t: Double) {
_translation.setToInterpolated(a.translation, b.translation, t)
_rotation.setToInterpolated(a.rotation, b.rotation, t)
_scale.setToInterpolated(a.scale, b.scale, t)
matrixDirty = true
}
override fun toString(): String = "Transform3D(translation=$translation,rotation=$rotation,scale=$scale)"
}
typealias PerspectiveCamera3D = Camera3D.Perspective

View File

@@ -0,0 +1,71 @@
package com.soywiz.korge.experimental.s3d.model.internal
import com.soywiz.korma.geom.*
import com.soywiz.korma.geom.interpolate
import com.soywiz.korma.interpolation.*
import kotlin.math.*
fun Vector3D.Companion.lengthSq(x: Double, y: Double, z: Double, w: Double) = x * x + y * y + z * z + w * w
fun Vector3D.Companion.length(x: Double, y: Double, z: Double, w: Double) = sqrt(lengthSq(x, y, z, w))
fun Quaternion.normalize(v: Quaternion = this): Quaternion {
val length = 1.0 / Vector3D.length(v.x, v.y, v.z, v.w)
return this.setTo(v.x / length, v.y / length, v.z / length, v.w / length)
}
// @TODO: Make Quaternions interpolable
object Quaternion_Companion
fun dotProduct(l: Quaternion, r: Quaternion): Double = l.x * r.x + l.y * r.y + l.z * r.z + l.w * r.w
operator fun Quaternion.unaryMinus(): Quaternion = Quaternion(-x, -y, -z, -w)
operator fun Quaternion.plus(other: Quaternion): Quaternion = Quaternion(x + other.x, y + other.y, z + other.z, w + other.w)
operator fun Quaternion.minus(other: Quaternion): Quaternion = Quaternion(x - other.x, y - other.y, z - other.z, w - other.w)
operator fun Quaternion.times(scale: Double): Quaternion = Quaternion(x * scale, y * scale, z * scale, w * scale)
operator fun Double.times(scale: Quaternion): Quaternion = scale.times(this)
fun Quaternion.negate() = this.setTo(-x, -y, -z, -w)
inline fun Quaternion.setToFunc(l: Quaternion, r: Quaternion, func: (l: Double, r: Double) -> Double) = setTo(
func(l.x, r.x),
func(l.y, r.y),
func(l.z, r.z),
func(l.w, r.w)
)
inline fun Vector3D.setToFunc(l: Vector3D, r: Vector3D, func: (l: Float, r: Float) -> Float) = setTo(
func(l.x, r.x),
func(l.y, r.y),
func(l.z, r.z),
func(l.w, r.w)
)
// @TODO: Allocations and temps!
private val tleft: Quaternion = Quaternion()
private val tright: Quaternion = Quaternion()
fun Quaternion.setToSlerp(left: Quaternion, right: Quaternion, t: Double): Quaternion {
val tleft = tleft.copyFrom(left).normalize()
val tright = tright.copyFrom(right).normalize()
var dot = dotProduct(tleft, right)
if (dot < 0.0f) {
tright.negate()
dot = -dot
}
if (dot > 0.99995f) return setToFunc(tleft, tright) { l, r -> l + t * (r - l) }
val angle0 = acos(dot)
val angle1 = angle0 * t
val s1 = sin(angle1) / sin(angle0)
val s0 = cos(angle1) - dot * s1
return setToFunc(tleft, tright) { l, r -> (s0 * l) + (s1 * r) }
}
fun Quaternion.setToInterpolated(left: Quaternion, right: Quaternion, t: Double): Quaternion = setToSlerp(left, right, t)
fun Vector3D.setToInterpolated(left: Vector3D, right: Vector3D, t: Double): Vector3D = setToFunc(left, right) { l, r -> t.interpolate(l, r) }

View File

@@ -147,7 +147,8 @@ object Demo3 {
//val library = resourcesVfs["cilinder.dae"].readColladaLibrary()
//val library = resourcesVfs["box_textured.dae"].readColladaLibrary()
//val library = resourcesVfs["monkey.dae"].readColladaLibrary()
val library = resourcesVfs["monkey-smooth.dae"].readColladaLibrary()
//val library = resourcesVfs["monkey-smooth.dae"].readColladaLibrary()
val library = resourcesVfs["monkey_smooth_two_camera.dae"].readColladaLibrary()
//val library = resourcesVfs["shape2.dae"].readColladaLibrary()
//val library = resourcesVfs["skinning.dae"].readColladaLibrary()
//val library = resourcesVfs["Fallera.dae"].readColladaLibrary()
@@ -169,10 +170,15 @@ object Demo3 {
//cube.mesh.texture = tex
val mainSceneView = library.mainScene.instantiate()
val cameras = mainSceneView.findByType<Camera3D>()
val camera1 = cameras.first().clone()
val camera2 = cameras.last().clone()
//ambientColor = Colors.RED
//ambientColor = Colors.WHITE
//ambientColor = Colors.WHITE
camera = mainSceneView.findByType<Camera3D>().first()
camera = camera1.clone()
this += mainSceneView
//this += box()
@@ -197,6 +203,19 @@ object Demo3 {
tick++
}
*/
launchImmediately {
while (true) {
tween(time = 2.seconds, easing = Easing.SMOOTH) {
camera.localTransform.setToInterpolated(camera1.localTransform, camera2.localTransform, it)
}
tween(time = 2.seconds, easing = Easing.SMOOTH) {
camera.localTransform.setToInterpolated(camera2.localTransform, camera1.localTransform, it)
}
}
}
//println(camera1.localTransform)
//println(camera2.localTransform)
}
}
}

File diff suppressed because one or more lines are too long