More work on 3d

This commit is contained in:
soywiz
2019-03-12 06:05:27 +01:00
parent 59e807405d
commit 24d96c67f0
11 changed files with 670 additions and 119 deletions

View File

@@ -75,6 +75,7 @@ class Transform3D {
private val _rotation = Quaternion()
private val _scale = Scale3D(1, 1, 1)
private fun updateTRS() {
transformDirty = false
matrix.getTRS(_translation, rotation, _scale)
transformDirty = false
}
@@ -93,8 +94,8 @@ class Transform3D {
}
fun setMatrix(mat: Matrix3D) {
this.matrix.copyFrom(mat)
transformDirty = true
this.matrix.copyFrom(mat)
}
@PublishedApi

View File

@@ -11,6 +11,7 @@ object Shaders3D {
operator fun Operand.get(index: Operand) = Program.ArrayAccess(this, index)
val u_Shiness = Uniform("u_shiness", VarType.Float1)
val u_AmbientColor = Uniform("u_ambientColor", VarType.Float4)
val u_ProjMat = Uniform("u_ProjMat", VarType.Mat4)
val u_ViewMat = Uniform("u_ViewMat", VarType.Mat4)
val u_BindMat = Uniform("u_BindMat", VarType.Mat4)
@@ -47,10 +48,9 @@ object Shaders3D {
)
class LightAttributes(val id: Int) {
val sourcePos = Uniform("light${id}_pos", VarType.Float3)
val diffuse = Uniform("light${id}_diffuse", VarType.Float4)
val specular = Uniform("light${id}_specular", VarType.Float4)
val ambient = Uniform("light${id}_ambient", VarType.Float4)
val u_sourcePos = Uniform("light${id}_pos", VarType.Float3)
val u_color = Uniform("light${id}_color", VarType.Float4)
val u_attenuation = Uniform("light${id}_attenuation", VarType.Float3)
}
val lights = (0 until 4).map { LightAttributes(it) }
@@ -63,13 +63,33 @@ object Shaders3D {
val E = createTemp(VarType.Float3)
val R = createTemp(VarType.Float3)
SET(L, normalize(light.sourcePos["xyz"] - v))
val attenuation = createTemp(VarType.Float1)
val dist = createTemp(VarType.Float1)
val NdotL = createTemp(VarType.Float1)
val lightDir = createTemp(VarType.Float3)
SET(L, normalize(light.u_sourcePos["xyz"] - v))
SET(E, normalize(-v)) // we are in Eye Coordinates, so EyePos is (0,0,0)
SET(R, normalize(-reflect(L, N)))
SET(out["rgb"], out["rgb"] + light.ambient["rgb"])
SET(out["rgb"], out["rgb"] + clamp(light.diffuse * max(dot(N, L), 0f.lit), 0f.lit, 1f.lit)["rgb"])
SET(out["rgb"], out["rgb"] + clamp(light.specular * pow(max(dot(R, E), 0f.lit), 0.3f.lit * u_Shiness), 0f.lit, 1f.lit)["rgb"])
val constantAttenuation = light.u_attenuation.x
val linearAttenuation = light.u_attenuation.y
val quadraticAttenuation = light.u_attenuation.z
SET(lightDir, light.u_sourcePos["xyz"] - v_Pos)
SET(dist, length(lightDir))
//SET(dist, length(vec3(4f.lit, 1f.lit, 6f.lit) - vec3(0f.lit, 0f.lit, 0f.lit)))
SET(attenuation, 1f.lit / (constantAttenuation + linearAttenuation * dist + quadraticAttenuation * dist * dist))
//SET(attenuation, 1f.lit / (1f.lit + 0f.lit * dist + 0.00111109f.lit * dist * dist))
//SET(attenuation, 0.9.lit)
SET(NdotL, max(dot(normalize(N), normalize(lightDir)), 0f.lit))
IF(NdotL ge 0f.lit) {
SET(out["rgb"], out["rgb"] + (light.u_color["rgb"] * NdotL + u_AmbientColor["rgb"]) * attenuation)
}
//SET(out["rgb"], out["rgb"] * attenuation)
//SET(out["rgb"], out["rgb"] + clamp(light.diffuse * max(dot(N, L), 0f.lit), 0f.lit, 1f.lit)["rgb"])
//SET(out["rgb"], out["rgb"] + clamp(light.specular * pow(max(dot(R, E), 0f.lit), 0.3f.lit * u_Shiness), 0f.lit, 1f.lit)["rgb"])
}
@ThreadLocal
@@ -96,20 +116,30 @@ object Shaders3D {
val skinMatrix = createTemp(VarType.Mat4)
val localPos = createTemp(VarType.Float4)
val localNorm = createTemp(VarType.Float4)
SET(localPos, vec4(1f.lit))
SET(localNorm, vec4(0f.lit))
if (nweights == 0) {
SET(skinMatrix, mat4Identity())
SET(localPos, vec4(a_pos, 1f.lit))
SET(localNorm, vec4(a_norm, 0f.lit))
} else {
for (wIndex in 0 until nweights) {
IF(getBoneIndex(wIndex) ge 0.lit) {
SET(skinMatrix, skinMatrix + (getBone(wIndex) * getWeight(wIndex)))
SET(skinMatrix, getBone(wIndex))
SET(localPos, localPos + skinMatrix * vec4(a_pos, 1f.lit) * getWeight(wIndex))
SET(localNorm, localNorm + skinMatrix * vec4(a_norm, 0f.lit) * getWeight(wIndex))
}
}
}
SET(modelViewMat, u_ModMat * u_ViewMat)
SET(normalMat, u_NormMat)
SET(v_Pos, vec3(modelViewMat * u_BindMat * skinMatrix * vec4(a_pos, 1f.lit)))
SET(v_Norm, vec3(normalMat * u_BindMat * skinMatrix * vec4(a_norm, 1f.lit)))
SET(v_Pos, vec3(modelViewMat * u_BindMat * localPos))
SET(v_Norm, vec3(normalMat * u_BindMat * localNorm))
if (hasTexture) {
SET(v_TexCoords, a_tex["xy"])
}

View File

@@ -5,6 +5,7 @@ import com.soywiz.kds.iterators.*
import com.soywiz.kmem.*
import com.soywiz.korag.*
import com.soywiz.korag.shader.*
import com.soywiz.korge.experimental.s3d.model.internal.*
import com.soywiz.korge.render.*
import com.soywiz.korge.view.*
import com.soywiz.korim.bitmap.*
@@ -19,32 +20,25 @@ class Views3D {
fun Container3D.light(callback: Light3D.() -> Unit = {}) = Light3D().apply(callback).addTo(this)
class Light3D : View3D() {
var diffuseColor = Colors.WHITE
var specularColor = Colors.WHITE
var ambientColor = Colors.WHITE
var diffusePower = 1.0
var specularPower = 0.2
var ambientPower = 0.1
var power = 1.0
internal val tempArray1 = FloatArray(4)
internal val tempArray2 = FloatArray(4)
internal val tempArray3 = FloatArray(4)
open class Light3D(
var color: RGBA = Colors.WHITE,
var constantAttenuation: Double = 1.0,
var linearAttenuation: Double = 0.0,
var quadraticAttenuation: Double = 0.00111109
) : View3D() {
internal val tempVec1 = Vector3D()
internal val tempVec2 = Vector3D()
//val diffuseColorPremult get() = diffuseColor.withAd(power).premultiplied
//val specularColorPremult get() = specularColor.withAd(power).premultiplied
//val ambientColorPremult get() = ambientColor.withAd(power).premultiplied
fun diffuseColor(color: RGBA): Light3D = this.apply { this.diffuseColor = color }
fun specularColor(color: RGBA): Light3D = this.apply { this.specularColor = color }
fun ambientColor(color: RGBA): Light3D = this.apply { this.ambientColor = color }
fun colors(ambient: RGBA, diffuse: RGBA = ambient, specular: RGBA = diffuse) = this.diffuseColor(diffuse).specularColor(specular).ambientColor(ambient)
fun power(globalPower: Double = 1.0, diffusePower: Double = 1.0, specularPower: Double = 0.2, ambientPower: Double = 0.1) = apply {
this.power = globalPower
this.diffusePower = diffusePower
this.specularPower = specularPower
this.ambientPower = ambientPower
fun setTo(
color: RGBA = Colors.WHITE,
constantAttenuation: Double = 1.0,
linearAttenuation: Double = 0.0,
quadraticAttenuation: Double = 0.00111109
) = this.apply {
this.color = color
this.constantAttenuation = constantAttenuation
this.linearAttenuation = linearAttenuation
this.quadraticAttenuation = quadraticAttenuation
}
override fun render(ctx: RenderContext3D) {
@@ -53,7 +47,10 @@ class Light3D : View3D() {
class Stage3D(val views: Views3D) : Container3D() {
lateinit var view: Stage3DView
var camera = Camera3D.Perspective().apply {
//var ambientColor: RGBA = Colors.WHITE
var ambientColor: RGBA = Colors.BLACK // No ambient light
var ambientPower: Double = 0.3
var camera: Camera3D = Camera3D.Perspective().apply {
positionLookingAt(0, 1, -10, 0, 0, 0)
}
}
@@ -72,6 +69,7 @@ class Stage3DView(val stage3D: Stage3D) : View() {
ctx3D.rctx = ctx
ctx3D.projMat.copyFrom(stage3D.camera.getProjMatrix(ctx.ag.backWidth.toDouble(), ctx.ag.backHeight.toDouble()))
ctx3D.cameraMat.copyFrom(stage3D.camera.localTransform.matrix)
ctx3D.ambientColor.setToColorPremultiplied(stage3D.ambientColor).scale(stage3D.ambientPower)
ctx3D.cameraMatInv.invert(stage3D.camera.localTransform.matrix)
ctx3D.projCameraMat.multiply(ctx3D.projMat, ctx3D.cameraMatInv)
ctx3D.lights.clear()
@@ -84,6 +82,8 @@ class Stage3DView(val stage3D: Stage3D) : View() {
}
}
fun View3D?.foreachDescendant(handler: (View3D) -> Unit) {
if (this != null) {
handler(this)
@@ -108,9 +108,11 @@ class RenderContext3D() {
val cameraMat: Matrix3D = Matrix3D()
val cameraMatInv: Matrix3D = Matrix3D()
val dynamicVertexBufferPool = Pool { ag.createVertexBuffer() }
val ambientColor: Vector3D = Vector3D()
}
abstract class View3D {
var id: String? = null
var name: String? = null
val localTransform = Transform3D()
@@ -140,6 +142,18 @@ abstract class View3D {
open class Container3D : View3D() {
val children = arrayListOf<View3D>()
fun removeChild(child: View3D) {
children.remove(child)
}
fun addChild(child: View3D) {
child.removeFromParent()
children += child
child.parent = this
}
operator fun plusAssign(child: View3D) = addChild(child)
override fun render(ctx: RenderContext3D) {
children.fastForEach {
it.render(ctx)
@@ -147,12 +161,23 @@ open class Container3D : View3D() {
}
}
fun View3D.removeFromParent() {
parent?.removeChild(this)
parent = null
}
inline fun <reified T : View3D> View3D?.findByType() = sequence<T> {
for (it in descendants()) {
if (it is T) yield(it)
}
}
inline fun <reified T : View3D> View3D?.findByTypeWithName(name: String) = sequence<T> {
for (it in descendants()) {
if (it is T && it.name == name) yield(it)
}
}
fun View3D?.descendants(): Sequence<View3D> = sequence<View3D> {
val view = this@descendants ?: return@sequence
yield(view)
@@ -198,9 +223,7 @@ inline fun <T : View3D> T.positionLookingAt(px: Number, py: Number, pz: Number,
}
fun <T : View3D> T.addTo(container: Container3D) = this.apply {
this.parent?.children?.remove(this)
container.children += this
this.parent = container
container.addChild(this)
}
data class Bone3D(
@@ -214,6 +237,15 @@ data class Skeleton3D(val bindShapeMatrix: Matrix3D, val bones: List<Bone3D>) {
}
class Mesh3D constructor(val data: FloatArray, val layout: VertexLayout, val program: Program?, val drawType: AG.DrawType, val maxWeights: Int = 0) {
val fbuffer by lazy {
FBuffer.alloc(data.size * 4).apply {
setAlignedArrayFloat32(0, this@Mesh3D.data, 0, this@Mesh3D.data.size)
}
//FBuffer.wrap(MemBufferAlloc(data.size * 4)).apply {
// arraycopy(this@Mesh3D.data, 0, this@apply.mem, 0, this@Mesh3D.data.size) // Bug in kmem-js?
//}
}
var skeleton: Skeleton3D? = null
var texture: Bitmap? = null
@@ -309,7 +341,9 @@ open class ViewWithMesh3D(var mesh: Mesh3D) : View3D() {
val ag = ctx.ag
ctx.dynamicVertexBufferPool.alloc { vertexBuffer ->
vertexBuffer.upload(mesh.data)
//vertexBuffer.upload(mesh.data)
vertexBuffer.upload(mesh.fbuffer)
//tempMat2.invert()
//tempMat3.multiply(ctx.cameraMatInv, this.localTransform.matrix)
//tempMat3.multiply(ctx.cameraMatInv, Matrix3D().invert(this.localTransform.matrix))
@@ -356,35 +390,15 @@ open class ViewWithMesh3D(var mesh: Mesh3D) : View3D() {
this[u_BindMat] = ctx.bindMat4.identity()
}
this[u_AmbientColor] = ctx.ambientColor
ctx.lights.fastForEachWithIndex { index, light: Light3D ->
this[lights[index].sourcePos] = light.localTransform.translation.data
val diffuse = light.diffuseColor
val specular = light.specularColor
val ambient = light.ambientColor
//println(light.diffuseColor.withAd(1.0))
//println(diffuse)
//println(specular)
//println(ambient)
this[lights[index].diffuse] = light.tempArray1.apply {
val scale = (light.power * light.diffusePower).toFloat()
this[0] = (diffuse.rf * scale)
this[1] = (diffuse.gf * scale)
this[2] = (diffuse.bf * scale)
}
this[lights[index].specular] = light.tempArray2.apply {
val scale = (light.power * light.specularPower).toFloat()
this[0] = (specular.rf * scale)
this[1] = (specular.gf * scale)
this[2] = (specular.bf * scale)
}
this[lights[index].ambient] = light.tempArray3.apply {
val scale = (light.power * light.ambientPower).toFloat()
this[0] = (ambient.rf * scale)
this[1] = (ambient.gf * scale)
this[2] = (ambient.bf * scale)
}
val lightColor = light.color
this[lights[index].u_sourcePos] = light.localTransform.translation
//println("light.localTransform.translation:${light.localTransform.translation}")
this[lights[index].u_color] = light.tempVec1.setTo(lightColor.rf, lightColor.gf, lightColor.bf, 1f)
//println(light.tempVec1.setTo(lightColor.rf, lightColor.gf, lightColor.bf, 1f))
this[lights[index].u_attenuation] = light.tempVec2.setTo(light.constantAttenuation, light.linearAttenuation, light.quadraticAttenuation)
}
},
renderState = rs

View File

@@ -6,6 +6,7 @@ import com.soywiz.korag.*
import com.soywiz.korag.shader.*
import com.soywiz.korge.experimental.s3d.*
import com.soywiz.korge.experimental.s3d.model.internal.*
import com.soywiz.korim.color.*
import com.soywiz.korio.file.*
import com.soywiz.korio.serialization.xml.*
import com.soywiz.korio.util.*
@@ -52,9 +53,9 @@ class ColladaParser {
for (skin in skins) {
library.skins[skin.controllerId] = skin
}
generateGeometries(geometries, skins)
parseVisualScenes(xml)
parseScene(xml)
generateGeometries(geometries, skins)
}
fun Library3D.generateGeometries(geometries: List<Geometry>, skins: List<Skin>) {
@@ -216,8 +217,9 @@ class ColladaParser {
//println(combinedData.toString())
geometryDefs[geom.id] = Library3D.RawGeometryDef(
geometryDefs[geom.id] = Library3D.GeometryDef(
Mesh3D(
//combinedData.toFloatArray().toFBuffer(),
combinedData.toFloatArray(),
VertexLayout(buildList {
add(Shaders3D.a_pos)
@@ -247,6 +249,13 @@ class ColladaParser {
fun Library3D.parseScene(xml: Xml) {
val scene = xml["scene"]
for (instance_visual_scene in scene["instance_visual_scene"]) {
val id = instance_visual_scene.str("url").trim('#')
val scene = scenes[id]
if (scene != null) {
mainScene.children += scene
}
}
}
fun parseControllers(xml: Xml): List<Skin> {
@@ -322,9 +331,27 @@ class ColladaParser {
fun Library3D.parseLights(xml: Xml) {
for (light in xml["library_lights"]["light"]) {
val id = light.getString("id")
val name = light.getString("name")
var lightDef: Library3D.LightDef? = null
val id = light.str("id")
val name = light.str("name")
log { "Light id=$id, name=$name" }
for (technique in light["technique_common"].allNodeChildren) {
when (technique.nameLC) {
"point" -> {
val color = technique["color"].firstOrNull()?.text?.reader()?.readVector3D() ?: Vector3D(1, 1, 1)
val constant_attenuation = technique["constant_attenuation"].firstOrNull()?.text?.toDoubleOrNull() ?: 1.0
val linear_attenuation = technique["linear_attenuation"].firstOrNull()?.text?.toDoubleOrNull() ?: 0.0
val quadratic_attenuation = technique["quadratic_attenuation"].firstOrNull()?.text?.toDoubleOrNull() ?: 0.00111109
lightDef = Library3D.PointLightDef(RGBA.float(color.x, color.y, color.z, 1f), constant_attenuation, linear_attenuation, quadratic_attenuation)
}
else -> {
println("WARNING: Unsupported light.technique_common.${technique.nameLC}")
}
}
}
if (lightDef != null) {
lightDefs[id] = lightDef
}
}
}
@@ -419,35 +446,109 @@ class ColladaParser {
fun Library3D.parseVisualScenes(xml: Xml) {
for (vscene in xml["library_visual_scenes"]["visual_scene"]) {
val id = vscene.getString("id")
val name = vscene.getString("name")
log { "VisualScene id=$id, name=$name" }
val scene = Library3D.Scene3D()
scene.id = vscene.str("id")
scene.name = vscene.str("name")
for (node in vscene["node"]) {
val id = node.getString("id")
val name = node.getString("name")
var transform = Matrix3D()
node.allNodeChildren.fastForEach { v ->
when (v.nameLC) {
"matrix" -> {
val sid = v.getString("sid")
val matrix = v.text.reader().readMatrix3D()
when (sid) {
"transform" -> {
transform = matrix
}
else -> {
log { " Unhandled matrix sid=$sid" }
}
}
}
else -> {
log { " Unhandled ${v.nameLC}" }
}
val instance = parseVisualSceneNode(node)
scene.children += instance
}
scenes[scene.id] = scene
}
}
fun Library3D.parseVisualSceneNode(node: Xml): Library3D.Instance3D {
val instance = Library3D.Instance3D()
var location: Vector3D? = null
var scale: Vector3D? = null
var rotationX: Vector3D? = null
var rotationY: Vector3D? = null
var rotationZ: Vector3D? = null
instance.id = node.str("id")
instance.name = node.str("name")
instance.type = node.str("type")
for (child in node.allNodeChildren) {
when (child.nameLC) {
"matrix" -> {
val sid = child.str("sid")
when (sid) {
"transform" -> instance.transform.copyFrom(child.text.reader().readMatrix3D())
else -> println("WARNING: Unsupported node.matrix.sid=$sid")
}
}
log { " Node id=$id, name=$name, transform=$transform" }
"translate" -> {
val sid = child.str("sid")
when (sid) {
"location" -> location = child.text.reader().readVector3D()
else -> println("WARNING: Unsupported node.translate.sid=$sid")
}
}
"rotate" -> {
val sid = child.str("sid")
when (sid) {
"rotationX" -> rotationX = child.text.reader().readVector3D()
"rotationY" -> rotationY = child.text.reader().readVector3D()
"rotationZ" -> rotationZ = child.text.reader().readVector3D()
else -> println("WARNING: Unsupported node.rotate.sid=$sid")
}
}
"scale" -> {
val sid = child.str("sid")
when (sid) {
"scale" -> scale = child.text.reader().readVector3D()
else -> println("WARNING: Unsupported node.scale.sid=$sid")
}
}
"instance_camera" -> {
val cameraId = child.str("url").trim('#')
instance.def = cameraDefs[cameraId]
}
"instance_light" -> {
val lightId = child.str("url").trim('#')
instance.def = lightDefs[lightId]
}
"instance_geometry" -> {
val geometryId = child.str("url").trim('#')
val geometryName = child.str("name")
instance.def = geometryDefs[geometryId]
}
"node" -> {
val childInstance = parseVisualSceneNode(child)
instance.children.add(childInstance)
}
"extra" -> {
}
else -> {
println("WARNING: Unsupported node.${child.nameLC}")
}
}
}
if (location != null || scale != null || rotationX != null || rotationY != null || rotationZ != null) {
val trns = location ?: Vector3D(0, 0, 0, 1)
val scl = scale ?: Vector3D(1, 1, 1)
val rotX = rotationX ?: Vector3D(1, 0, 0, 0)
val rotY = rotationY ?: Vector3D(0, 1, 0, 0)
val rotZ = rotationZ ?: Vector3D(0, 0, 1, 0)
rotationVectorToEulerRotation(rotX)
instance.transform.setTRS(
trns,
Quaternion().setTo(combine(rotationVectorToEulerRotation(rotX), rotationVectorToEulerRotation(rotY), rotationVectorToEulerRotation(rotZ))),
scl
)
}
return instance
}
private fun combine(a: EulerRotation, b: EulerRotation, c: EulerRotation, out: EulerRotation = EulerRotation()): EulerRotation {
return out.setTo(a.x + b.x + c.x, a.y + b.y + c.y, a.z + b.z + c.z)
}
private fun rotationVectorToEulerRotation(vec: Vector3D, out: EulerRotation = EulerRotation()): EulerRotation {
val degrees = vec.w.degrees
return out.setTo(degrees * vec.x, degrees * vec.y, degrees * vec.z)
}
val sourceArrayParams = FastStringMap<SourceParam>()
@@ -537,3 +638,5 @@ class ColladaParser {
@Deprecated("", ReplaceWith("log { str }", "com.soywiz.korge.experimental.s3d.model.ColladaParser.log"))
inline fun log(str: String) = log { str }
}
private val Iterable<Xml>.allNodeChildren: Iterable<Xml> get() = this.flatMap(Xml::allNodeChildren)

View File

@@ -2,31 +2,101 @@ package com.soywiz.korge.experimental.s3d.model
import com.soywiz.kds.*
import com.soywiz.korge.experimental.s3d.*
import com.soywiz.korim.color.*
import com.soywiz.korma.geom.*
data class Library3D(
val cameraDefs: FastStringMap<CameraDef> = FastStringMap(),
val lightDefs: FastStringMap<LightDef> = FastStringMap(),
val materialDefs: FastStringMap<MaterialDef> = FastStringMap(),
val geometryDefs: FastStringMap<GeometryDef> = FastStringMap(),
val skins: FastStringMap<ColladaParser.Skin> = FastStringMap()
) {
val library = this
open class CameraDef
val mainScene = Scene3D().apply {
id = "MainScene"
name = "MainScene"
}
var scenes = FastStringMap<Scene3D>()
open class Instance3D {
val transform = Matrix3D()
var def: Def? = null
val children = arrayListOf<Instance3D>()
var id: String = ""
var name: String = ""
var type: String = ""
}
open class Scene3D : Instance3D() {
}
open class Def
open class ObjectDef : Def()
open class MaterialDef : Def()
open class LightDef : ObjectDef()
open class CameraDef : ObjectDef()
data class PerspectiveCameraDef(val xfov: Angle, val zmin: Double, val zmax: Double) : CameraDef()
open class GeometryDef
//data class RawGeometryDef(val data: FloatArray, val hasPos: Boolean, val hasNormal: Boolean, val hasUV: Boolean) : GeometryDef()
data class RawGeometryDef(
data class GeometryDef(
val mesh: Mesh3D,
val skin: SkinDef? = null
) : GeometryDef()
) : ObjectDef()
data class BoneDef(val name: String, val pose: Matrix3D) {
data class BoneDef(val name: String, val pose: Matrix3D) : Def() {
fun toBone() = Bone3D(name, pose.clone())
}
data class SkinDef(
val bindShapeMatrix: Matrix3D,
val bones: List<BoneDef>
)
) : Def()
class PointLightDef(
val color: RGBA,
val constantAttenuation: Double,
val linearAttenuation: Double,
val quadraticAttenuation: Double
) : LightDef()
}
fun Library3D.Instance3D.instantiate(): View3D {
val def = this.def
val view: View3D = when (def) {
null -> {
Container3D().also { container ->
for (child in children) {
container.addChild(child.instantiate())
}
}
}
is Library3D.GeometryDef -> {
ViewWithMesh3D(def.mesh)
}
is Library3D.PerspectiveCameraDef -> {
Camera3D.Perspective(def.xfov, def.zmin, def.zmax)
}
is Library3D.PointLightDef -> {
Light3D(def.color, def.constantAttenuation, def.linearAttenuation, def.quadraticAttenuation)
}
else -> TODO("def=$def")
}
view.id = this.id
view.name = this.name
//view.localTransform.setMatrix(this.transform.clone().transpose())
view.localTransform.setMatrix(this.transform)
if (def is Library3D.PointLightDef) {
println(view.localTransform.matrix)
println(view.localTransform.translation)
println(view.localTransform.rotation)
println(view.localTransform.scale)
println("def: $def")
}
return view
}

View File

@@ -0,0 +1,18 @@
package com.soywiz.korge.experimental.s3d.model.internal
import com.soywiz.korim.color.*
import com.soywiz.korma.geom.*
internal fun Vector3D.setToColorPremultiplied(col: RGBA): Vector3D = this.apply { col.toPremultipliedVector3D(this) }
internal fun Vector3D.setToColor(col: RGBA): Vector3D = this.apply { col.toPremultipliedVector3D(this) }
internal fun RGBA.toPremultipliedVector3D(out: Vector3D = Vector3D()): Vector3D = out.setTo(
rf * af, gf * af, bf * af, 1f
)
internal fun RGBA.toVector3D(out: Vector3D = Vector3D()): Vector3D = out.setTo(
rf, gf, bf, af
)
fun Vector3D.scale(scale: Float) = this.setTo(this.x * scale, this.y * scale, this.z * scale, this.w * scale)
inline fun Vector3D.scale(scale: Number) = scale(scale.toFloat())

View File

@@ -41,10 +41,18 @@ internal fun StrReader.readInts(list: com.soywiz.kds.IntArrayList = com.soywiz.k
return list
}
internal fun StrReader.readVector3D(): com.soywiz.korma.geom.Vector3D {
val f = readFloats(com.soywiz.kds.FloatArrayList())
return when {
f.size == 4 -> com.soywiz.korma.geom.Vector3D(f[0], f[1], f[2], f[3])
else -> com.soywiz.korma.geom.Vector3D(f[0], f[1], f[2])
}
}
internal fun StrReader.readMatrix3D(): com.soywiz.korma.geom.Matrix3D {
val f = readFloats(com.soywiz.kds.FloatArrayList())
if (f.size == 16) {
return com.soywiz.korma.geom.Matrix3D().setColumns( // This is correct
return com.soywiz.korma.geom.Matrix3D().setRows(
f[0], f[1], f[2], f[3],
f[4], f[5], f[6], f[7],
f[8], f[9], f[10], f[11],

View File

@@ -5,7 +5,6 @@ import com.soywiz.korge.experimental.s3d.*
import com.soywiz.korge.experimental.s3d.model.*
import com.soywiz.korge.tween.*
import com.soywiz.korge.view.*
import com.soywiz.korim.bitmap.*
import com.soywiz.korim.color.*
import com.soywiz.korim.format.*
import com.soywiz.korio.*
@@ -16,7 +15,8 @@ import com.soywiz.korma.interpolation.*
import kotlin.jvm.*
//suspend fun main(args: Array<String>) = Demo3.main(args)
suspend fun main(args: Array<String>) = Demo3.main()
//suspend fun main(args: Array<String>) = Demo3.main()
suspend fun main(args: Array<String>) = Demo1.main()
object Demo1 {
@JvmStatic
@@ -70,8 +70,8 @@ object Demo2 {
//delay(10.seconds)
//println("delay")
scene3D {
val light1 = light().position(0, 10, +10).diffuseColor(Colors.RED)
val light2 = light().position(10, 0, +10).diffuseColor(Colors.BLUE)
val light1 = light().position(0, 10, +10).setTo(Colors.RED)
val light2 = light().position(10, 0, +10).setTo(Colors.BLUE)
launchImmediately {
while (true) {
@@ -87,7 +87,7 @@ object Demo2 {
val library = resourcesVfs["monkey-smooth.dae"].readColladaLibrary()
//val library = resourcesVfs["plane.dae"].readColladaLibrary()
//val cubeGeom = library.geometryDefs["Cube-mesh"]!! as Library3D.RawGeometryDef
val cubeGeom = library.geometryDefs.values.first() as Library3D.RawGeometryDef
val cubeGeom = library.geometryDefs.values.first() as Library3D.GeometryDef
val cube = mesh(cubeGeom.mesh).rotation(-90.degrees, 0.degrees, 0.degrees)
println(library)
/*
@@ -128,7 +128,7 @@ object Demo3 {
//delay(10.seconds)
//println("delay")
scene3D {
val light1 = light().position(0, 1, 1).colors(Colors.WHITE, Colors.WHITE, Colors.WHITE).power(1.0)
//val light1 = light().position(0, 1, 1).colors(Colors.WHITE, Colors.WHITE, Colors.WHITE).power(1.0)
/*
val light1 = light().position(0, 10, +10).colors(Colors.RED, Colors.RED, Colors.RED)
val light2 = light().position(10, 0, +10).colors(Colors.BLUE, Colors.BLUE, Colors.BLUE)
@@ -145,25 +145,36 @@ object Demo3 {
//val library = resourcesVfs["scene.dae"].readColladaLibrary()
//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["shape2.dae"].readColladaLibrary()
val library = resourcesVfs["skinning.dae"].readColladaLibrary()
//val library = resourcesVfs["skinning.dae"].readColladaLibrary()
//val library = resourcesVfs["Fallera.dae"].readColladaLibrary()
//val library = resourcesVfs["model.dae"].readColladaLibrary()
//val library = resourcesVfs["skinning_sample.dae"].readColladaLibrary()
//val library = resourcesVfs["box_textured.dae"].readColladaLibrary()
//val library = resourcesVfs["shape1.dae"].readColladaLibrary()
//val library = resourcesVfs["plane.dae"].readColladaLibrary()
//val cubeGeom = library.geometryDefs["Cube-mesh"]!! as Library3D.RawGeometryDef
val cubeGeom = library.geometryDefs.values.first() as Library3D.RawGeometryDef
val tex = resourcesVfs["korge.png"].readBitmapOptimized()
//val cubeGeom = library.geometryDefs.values.first() as Library3D.GeometryDef
//val tex = resourcesVfs["korge.png"].readBitmapOptimized()
//val tex = resourcesVfs["Fallera.jpg"].readBitmapOptimized()
//val tex = resourcesVfs["diffuse.png"].readBitmapOptimized()
//val cube = mesh(cubeGeom.mesh)
//val cube = mesh(cubeGeom.mesh).scale(0.02, 0.02, 0.02).rotation(z = 90.degrees)
//val cube = mesh(cubeGeom.mesh).scale(0.02, 0.02, 0.02).rotation(z = 90.degrees) // @TODO: Kotlin.JS BUG
//val cube = mesh(cubeGeom.mesh).scale(0.02, 0.02, 0.02).rotation(0.degrees, 0.degrees, 90.degrees)
//val cube = mesh(cubeGeom.mesh).rotation(y = 90.degrees) // @TODO: Kotlin.JS BUG
val cube = mesh(cubeGeom.mesh)
cube.mesh.texture = tex
//val cube = mesh(cubeGeom.mesh)
//cube.mesh.texture = tex
val mainSceneView = library.mainScene.instantiate()
//ambientColor = Colors.RED
//ambientColor = Colors.WHITE
//ambientColor = Colors.WHITE
camera = mainSceneView.findByType<Camera3D>().first()
this += mainSceneView
//this += box()
//val cube = mesh(cubeGeom.mesh).scale(0.02, 0.02, 0.02)
//val cube = mesh(cubeGeom.mesh).rotation(-90.degrees, 0.degrees, 0.degrees)
@@ -174,6 +185,7 @@ object Demo3 {
}
*/
/*
var tick = 0
addUpdatable {
val angle = (tick / 1.0).degrees
@@ -184,6 +196,7 @@ object Demo3 {
)
tick++
}
*/
}
}
}

View File

@@ -0,0 +1,294 @@
<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<asset>
<contributor>
<author>Blender User</author>
<authoring_tool>Blender 2.79.0 commit date:2018-03-22, commit time:14:10, hash:f4dc9f9</authoring_tool>
</contributor>
<created>2019-03-10T23:38:20</created>
<modified>2019-03-10T23:38:20</modified>
<unit name="meter" meter="1"/>
<up_axis>Z_UP</up_axis>
</asset>
<library_cameras>
<camera id="Camera-camera" name="Camera">
<optics>
<technique_common>
<perspective>
<xfov sid="xfov">49.13434</xfov>
<aspect_ratio>1.777778</aspect_ratio>
<znear sid="znear">0.1</znear>
<zfar sid="zfar">100</zfar>
</perspective>
</technique_common>
</optics>
<extra>
<technique profile="blender">
<shiftx sid="shiftx" type="float">0</shiftx>
<shifty sid="shifty" type="float">0</shifty>
<YF_dofdist sid="YF_dofdist" type="float">0</YF_dofdist>
</technique>
</extra>
</camera>
</library_cameras>
<library_lights>
<light id="Lamp_001-light" name="Lamp.001">
<technique_common>
<point>
<color sid="color">1 1 1</color>
<constant_attenuation>1</constant_attenuation>
<linear_attenuation>0</linear_attenuation>
<quadratic_attenuation>0.00111109</quadratic_attenuation>
</point>
</technique_common>
<extra>
<technique profile="blender">
<type sid="type" type="int">0</type>
<flag sid="flag" type="int">0</flag>
<mode sid="mode" type="int">8192</mode>
<gamma sid="blender_gamma" type="float">1</gamma>
<red sid="red" type="float">1</red>
<green sid="green" type="float">1</green>
<blue sid="blue" type="float">1</blue>
<shadow_r sid="blender_shadow_r" type="float">0</shadow_r>
<shadow_g sid="blender_shadow_g" type="float">0</shadow_g>
<shadow_b sid="blender_shadow_b" type="float">0</shadow_b>
<energy sid="blender_energy" type="float">1</energy>
<dist sid="blender_dist" type="float">29.99998</dist>
<spotsize sid="spotsize" type="float">75</spotsize>
<spotblend sid="spotblend" type="float">0.15</spotblend>
<halo_intensity sid="blnder_halo_intensity" type="float">1</halo_intensity>
<att1 sid="att1" type="float">0</att1>
<att2 sid="att2" type="float">1</att2>
<falloff_type sid="falloff_type" type="int">2</falloff_type>
<clipsta sid="clipsta" type="float">1.000799</clipsta>
<clipend sid="clipend" type="float">30.002</clipend>
<bias sid="bias" type="float">1</bias>
<soft sid="soft" type="float">3</soft>
<compressthresh sid="compressthresh" type="float">0.04999995</compressthresh>
<bufsize sid="bufsize" type="int">2880</bufsize>
<samp sid="samp" type="int">3</samp>
<buffers sid="buffers" type="int">1</buffers>
<filtertype sid="filtertype" type="int">0</filtertype>
<bufflag sid="bufflag" type="int">0</bufflag>
<buftype sid="buftype" type="int">2</buftype>
<ray_samp sid="ray_samp" type="int">1</ray_samp>
<ray_sampy sid="ray_sampy" type="int">1</ray_sampy>
<ray_sampz sid="ray_sampz" type="int">1</ray_sampz>
<ray_samp_type sid="ray_samp_type" type="int">0</ray_samp_type>
<area_shape sid="area_shape" type="int">1</area_shape>
<area_size sid="area_size" type="float">0.1</area_size>
<area_sizey sid="area_sizey" type="float">0.1</area_sizey>
<area_sizez sid="area_sizez" type="float">1</area_sizez>
<adapt_thresh sid="adapt_thresh" type="float">0.000999987</adapt_thresh>
<ray_samp_method sid="ray_samp_method" type="int">1</ray_samp_method>
<shadhalostep sid="shadhalostep" type="int">0</shadhalostep>
<sun_effect_type sid="sun_effect_type" type="int">0</sun_effect_type>
<skyblendtype sid="skyblendtype" type="int">1</skyblendtype>
<horizon_brightness sid="horizon_brightness" type="float">1</horizon_brightness>
<spread sid="spread" type="float">1</spread>
<sun_brightness sid="sun_brightness" type="float">1</sun_brightness>
<sun_size sid="sun_size" type="float">1</sun_size>
<backscattered_light sid="backscattered_light" type="float">1</backscattered_light>
<sun_intensity sid="sun_intensity" type="float">1</sun_intensity>
<atm_turbidity sid="atm_turbidity" type="float">2</atm_turbidity>
<atm_extinction_factor sid="atm_extinction_factor" type="float">1</atm_extinction_factor>
<atm_distance_factor sid="atm_distance_factor" type="float">1</atm_distance_factor>
<skyblendfac sid="skyblendfac" type="float">1</skyblendfac>
<sky_exposure sid="sky_exposure" type="float">1</sky_exposure>
<sky_colorspace sid="sky_colorspace" type="int">0</sky_colorspace>
</technique>
</extra>
</light>
<light id="Lamp-light" name="Lamp">
<technique_common>
<point>
<color sid="color">1 1 1</color>
<constant_attenuation>1</constant_attenuation>
<linear_attenuation>0</linear_attenuation>
<quadratic_attenuation>0.00111109</quadratic_attenuation>
</point>
</technique_common>
<extra>
<technique profile="blender">
<type sid="type" type="int">0</type>
<flag sid="flag" type="int">0</flag>
<mode sid="mode" type="int">8192</mode>
<gamma sid="blender_gamma" type="float">1</gamma>
<red sid="red" type="float">1</red>
<green sid="green" type="float">1</green>
<blue sid="blue" type="float">1</blue>
<shadow_r sid="blender_shadow_r" type="float">0</shadow_r>
<shadow_g sid="blender_shadow_g" type="float">0</shadow_g>
<shadow_b sid="blender_shadow_b" type="float">0</shadow_b>
<energy sid="blender_energy" type="float">1</energy>
<dist sid="blender_dist" type="float">29.99998</dist>
<spotsize sid="spotsize" type="float">75</spotsize>
<spotblend sid="spotblend" type="float">0.15</spotblend>
<halo_intensity sid="blnder_halo_intensity" type="float">1</halo_intensity>
<att1 sid="att1" type="float">0</att1>
<att2 sid="att2" type="float">1</att2>
<falloff_type sid="falloff_type" type="int">2</falloff_type>
<clipsta sid="clipsta" type="float">1.000799</clipsta>
<clipend sid="clipend" type="float">30.002</clipend>
<bias sid="bias" type="float">1</bias>
<soft sid="soft" type="float">3</soft>
<compressthresh sid="compressthresh" type="float">0.04999995</compressthresh>
<bufsize sid="bufsize" type="int">2880</bufsize>
<samp sid="samp" type="int">3</samp>
<buffers sid="buffers" type="int">1</buffers>
<filtertype sid="filtertype" type="int">0</filtertype>
<bufflag sid="bufflag" type="int">0</bufflag>
<buftype sid="buftype" type="int">2</buftype>
<ray_samp sid="ray_samp" type="int">1</ray_samp>
<ray_sampy sid="ray_sampy" type="int">1</ray_sampy>
<ray_sampz sid="ray_sampz" type="int">1</ray_sampz>
<ray_samp_type sid="ray_samp_type" type="int">0</ray_samp_type>
<area_shape sid="area_shape" type="int">1</area_shape>
<area_size sid="area_size" type="float">0.1</area_size>
<area_sizey sid="area_sizey" type="float">0.1</area_sizey>
<area_sizez sid="area_sizez" type="float">1</area_sizez>
<adapt_thresh sid="adapt_thresh" type="float">0.000999987</adapt_thresh>
<ray_samp_method sid="ray_samp_method" type="int">1</ray_samp_method>
<shadhalostep sid="shadhalostep" type="int">0</shadhalostep>
<sun_effect_type sid="sun_effect_type" type="int">0</sun_effect_type>
<skyblendtype sid="skyblendtype" type="int">1</skyblendtype>
<horizon_brightness sid="horizon_brightness" type="float">1</horizon_brightness>
<spread sid="spread" type="float">1</spread>
<sun_brightness sid="sun_brightness" type="float">1</sun_brightness>
<sun_size sid="sun_size" type="float">1</sun_size>
<backscattered_light sid="backscattered_light" type="float">1</backscattered_light>
<sun_intensity sid="sun_intensity" type="float">1</sun_intensity>
<atm_turbidity sid="atm_turbidity" type="float">2</atm_turbidity>
<atm_extinction_factor sid="atm_extinction_factor" type="float">1</atm_extinction_factor>
<atm_distance_factor sid="atm_distance_factor" type="float">1</atm_distance_factor>
<skyblendfac sid="skyblendfac" type="float">1</skyblendfac>
<sky_exposure sid="sky_exposure" type="float">1</sky_exposure>
<sky_colorspace sid="sky_colorspace" type="int">0</sky_colorspace>
</technique>
</extra>
</light>
</library_lights>
<library_images>
<image id="crate_png" name="crate_png">
<init_from>crate.png</init_from>
</image>
</library_images>
<library_effects>
<effect id="Material_001-effect">
<profile_COMMON>
<newparam sid="crate_png-surface">
<surface type="2D">
<init_from>crate_png</init_from>
</surface>
</newparam>
<newparam sid="crate_png-sampler">
<sampler2D>
<source>crate_png-surface</source>
</sampler2D>
</newparam>
<technique sid="common">
<phong>
<emission>
<color sid="emission">0 0 0 1</color>
</emission>
<ambient>
<color sid="ambient">0 0 0 1</color>
</ambient>
<diffuse>
<texture texture="crate_png-sampler"/>
</diffuse>
<specular>
<color sid="specular">0.5 0.5 0.5 1</color>
</specular>
<shininess>
<float sid="shininess">50</float>
</shininess>
<index_of_refraction>
<float sid="index_of_refraction">1</float>
</index_of_refraction>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<library_materials>
<material id="Material_001-material" name="Material_001">
<instance_effect url="#Material_001-effect"/>
</material>
</library_materials>
<library_geometries>
<geometry id="Cube-mesh" name="Cube">
<mesh>
<source id="Cube-mesh-positions">
<float_array id="Cube-mesh-positions-array" count="24">1 1 -1 1 -1 -1 -1 -0.9999998 -1 -0.9999997 1 -1 1 0.9999995 1 0.9999994 -1.000001 1 -1 -0.9999997 1 -1 1 1</float_array>
<technique_common>
<accessor source="#Cube-mesh-positions-array" count="8" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cube-mesh-normals">
<float_array id="Cube-mesh-normals-array" count="36">0 0 -1 0 0 1 1 0 -2.38419e-7 0 -1 -4.76837e-7 -1 2.38419e-7 -1.49012e-7 2.68221e-7 1 2.38419e-7 0 0 -1 0 0 1 1 -5.96046e-7 3.27825e-7 -4.76837e-7 -1 0 -1 2.38419e-7 -1.19209e-7 2.08616e-7 1 0</float_array>
<technique_common>
<accessor source="#Cube-mesh-normals-array" count="12" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cube-mesh-map-0">
<float_array id="Cube-mesh-map-0-array" count="72">0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 1 1 0 0 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 1</float_array>
<technique_common>
<accessor source="#Cube-mesh-map-0-array" count="36" stride="2">
<param name="S" type="float"/>
<param name="T" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="Cube-mesh-vertices">
<input semantic="POSITION" source="#Cube-mesh-positions"/>
</vertices>
<triangles material="Material_001-material" count="12">
<input semantic="VERTEX" source="#Cube-mesh-vertices" offset="0"/>
<input semantic="NORMAL" source="#Cube-mesh-normals" offset="1"/>
<input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="2" set="0"/>
<p>0 0 0 2 0 1 3 0 2 7 1 3 5 1 4 4 1 5 4 2 6 1 2 7 0 2 8 5 3 9 2 3 10 1 3 11 2 4 12 7 4 13 3 4 14 0 5 15 7 5 16 4 5 17 0 6 18 1 6 19 2 6 20 7 7 21 6 7 22 5 7 23 4 8 24 5 8 25 1 8 26 5 9 27 6 9 28 2 9 29 2 10 30 6 10 31 7 10 32 0 11 33 3 11 34 7 11 35</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_controllers/>
<library_visual_scenes>
<visual_scene id="Scene" name="Scene">
<node id="Lamp_001" name="Lamp_001" type="NODE">
<matrix sid="transform">-0.2908646 -0.7711008 0.5663932 4.076245 0.9551712 -0.1998834 0.2183912 -4.424634 -0.05518906 0.6045247 0.7946723 5.903862 0 0 0 1</matrix>
<instance_light url="#Lamp_001-light"/>
</node>
<node id="Camera" name="Camera" type="NODE">
<matrix sid="transform">0.6859207 -0.3240135 0.6515582 7.481132 0.7276763 0.3054208 -0.6141704 -6.50764 0 0.8953956 0.4452714 5.343665 0 0 0 1</matrix>
<instance_camera url="#Camera-camera"/>
</node>
<node id="Lamp" name="Lamp" type="NODE">
<matrix sid="transform">-0.2908646 -0.7711008 0.5663932 4.076245 0.9551712 -0.1998834 0.2183912 1.005454 -0.05518906 0.6045247 0.7946723 5.903862 0 0 0 1</matrix>
<instance_light url="#Lamp-light"/>
</node>
<node id="Cube" name="Cube" type="NODE">
<matrix sid="transform">1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix>
<instance_geometry url="#Cube-mesh" name="Cube">
<bind_material>
<technique_common>
<instance_material symbol="Material_001-material" target="#Material_001-material"/>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#Scene"/>
</scene>
</COLLADA>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB