More work on 3d

This commit is contained in:
soywiz
2019-03-13 23:09:20 +01:00
parent 060e85aee2
commit 9522ff18ac
5 changed files with 81 additions and 56 deletions

View File

@@ -15,7 +15,7 @@ object Shaders3D {
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)
val u_BindShapeMatrix = Uniform("u_BindMat", VarType.Mat4)
val u_ModMat = Uniform("u_ModMat", VarType.Mat4)
val u_NormMat = Uniform("u_NormMat", VarType.Mat4)
//val MAX_BONE_MATS = 16
@@ -156,14 +156,16 @@ object Shaders3D {
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(localPos, localPos + vec4(a_pos, 1f.lit) * getWeight(wIndex))
//SET(localNorm, localNorm + vec4(a_norm, 0f.lit) * getWeight(wIndex))
}
}
}
SET(modelViewMat, u_ModMat * u_ViewMat)
SET(normalMat, u_NormMat)
SET(v_Pos, vec3(modelViewMat * u_BindMat * localPos))
SET(v_Norm, vec3(normalMat * u_BindMat * localNorm))
SET(v_Pos, vec3(modelViewMat * u_BindShapeMatrix * localPos))
SET(v_Norm, vec3(normalMat * u_BindShapeMatrix * localNorm))
if (hasTexture) {
SET(v_TexCoords, a_tex["xy"])
}

View File

@@ -26,8 +26,8 @@ open class Light3D(
var linearAttenuation: Double = 0.0,
var quadraticAttenuation: Double = 0.00111109
) : View3D() {
internal val tempVec1 = Vector3D()
internal val tempVec2 = Vector3D()
internal val colorVec = Vector3D()
internal val attenuationVec = Vector3D()
fun setTo(
color: RGBA = Colors.WHITE,
@@ -227,12 +227,15 @@ fun <T : View3D> T.addTo(container: Container3D) = this.apply {
container.addChild(this)
}
data class Bone3D(
data class Bone3D constructor(
val name: String,
val matrix: Matrix3D
)
val invBindMatrix: Matrix3D
) {
//val finalMatrix: Matrix3D = invBindMatrix.clone()
val finalMatrix: Matrix3D = Matrix3D()
}
data class Skeleton3D(val bindShapeMatrix: Matrix3D, val bones: List<Bone3D>) {
data class Skin3D(val bindShapeMatrix: Matrix3D, val bones: List<Bone3D>) {
//val matrices = Array(bones.size) { Matrix3D() }
val matrices = Array(Shaders3D.MAX_BONE_MATS) { Matrix3D() }
}
@@ -264,6 +267,8 @@ class Mesh3D constructor(
val hasTexture: Boolean = false,
val maxWeights: Int = 0
) {
var skin: Skin3D? = null
val fbuffer by lazy {
FBuffer.alloc(data.size * 4).apply {
setAlignedArrayFloat32(0, this@Mesh3D.data, 0, this@Mesh3D.data.size)
@@ -273,7 +278,6 @@ class Mesh3D constructor(
//}
}
var skeleton: Skeleton3D? = null
var material: Material3D? = null
//val modelMat = Matrix3D()
@@ -350,7 +354,11 @@ inline fun Container3D.mesh(mesh: Mesh3D, callback: ViewWithMesh3D.() -> Unit =
return ViewWithMesh3D(mesh).apply(callback).addTo(this)
}
open class ViewWithMesh3D(var mesh: Mesh3D) : View3D() {
open class ViewWithMesh3D(
var mesh: Mesh3D,
var skeleton: View3D? = null
) : View3D() {
private val uniformValues = AG.UniformValues()
private val rs = AG.RenderState(depthFunc = AG.CompareMode.LESS_EQUAL)
//private val rs = AG.RenderState(depthFunc = AG.CompareMode.ALWAYS)
@@ -396,12 +404,14 @@ open class ViewWithMesh3D(var mesh: Mesh3D) : View3D() {
program = mesh.program ?: getProgram3D(ctx.lights.size.clamp(0, 4), mesh.maxWeights, meshMaterial, mesh.hasTexture),
vertexLayout = mesh.layout,
vertexCount = mesh.vertexCount,
blending = AG.Blending.NONE,
//vertexCount = 6 * 6,
uniforms = uniformValues.apply {
this[u_ProjMat] = ctx.projCameraMat
this[u_ViewMat] = localTransform.matrix
this[u_ModMat] = tempMat2.multiply(tempMat1.apply { prepareExtraModelMatrix(this) }, modelMat)
this[u_NormMat] = tempMat3.multiply(tempMat2, localTransform.matrix).invert().transpose()
//this[u_NormMat] = tempMat3.multiply(tempMat2, localTransform.matrix).invert().transpose()
this[u_NormMat] = tempMat3.multiply(tempMat2, localTransform.matrix).invert()
this[u_Shiness] = meshMaterial?.shiness ?: 0.5f
this[u_IndexOfRefraction] = meshMaterial?.indexOfRefraction ?: 1f
@@ -413,11 +423,11 @@ open class ViewWithMesh3D(var mesh: Mesh3D) : View3D() {
setMaterialLight(ctx, specular, meshMaterial.specular)
}
val skeleton = mesh.skeleton
val skeleton = mesh.skin
if (skeleton != null) {
this[u_BindMat] = ctx.bindMat4.copyFrom(skeleton.bindShapeMatrix)
this[u_BindShapeMatrix] = ctx.bindMat4.copyFrom(skeleton.bindShapeMatrix)
skeleton.bones.fastForEachWithIndex { index, bone ->
skeleton.matrices[index].copyFrom(bone.matrix)
skeleton.matrices[index].copyFrom(bone.finalMatrix)
//skeleton.matrices[index].copyFrom(bone.matrix)
//skeleton.matrices[index].identity()
}
@@ -428,7 +438,7 @@ open class ViewWithMesh3D(var mesh: Mesh3D) : View3D() {
//skeleton.matrices[0][0, 0] = 0.1f
this[u_BoneMats] = skeleton.matrices
} else {
this[u_BindMat] = ctx.bindMat4.identity()
this[u_BindShapeMatrix] = ctx.bindMat4.identity()
}
this[u_AmbientColor] = ctx.ambientColor
@@ -436,10 +446,8 @@ open class ViewWithMesh3D(var mesh: Mesh3D) : View3D() {
ctx.lights.fastForEachWithIndex { index, light: Light3D ->
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)
this[lights[index].u_color] = light.colorVec.setTo(lightColor.rf, lightColor.gf, lightColor.bf, 1f)
this[lights[index].u_attenuation] = light.attenuationVec.setTo(light.constantAttenuation, light.linearAttenuation, light.quadraticAttenuation)
}
},
renderState = rs

View File

@@ -26,8 +26,7 @@ class ColladaParser {
data class NamesSourceParam(override val name: String, val names: ArrayList<String>) : SourceParam
data class Source(val id: String, val params: FastStringMap<SourceParam>)
data class Input(val semantic: String, val offset: Int, val source: Source, val indices: IntArrayList)
data class Geometry(val id: String, val name: String, val inputs: FastStringMap<Input> = FastStringMap(), var materialId: String? = null) {
}
data class Geometry(val id: String, val name: String, val inputs: FastStringMap<Input> = FastStringMap(), var materialId: String? = null)
data class Skin(
val controllerId: String,
val controllerName: String,
@@ -54,7 +53,7 @@ class ColladaParser {
parseAnimations(xml)
val skins = parseControllers(xml)
for (skin in skins) {
library.skins[skin.controllerId] = skin
library.skinDefs[skin.controllerId] = skin
}
generateGeometries(geometries, skins)
parseVisualScenes(xml)
@@ -239,7 +238,7 @@ class ColladaParser {
maxWeights = maxWeights
).apply {
if (skinDef != null) {
this.skeleton = Skeleton3D(skinDef.bindShapeMatrix, skinDef.bones.map { it.toBone() })
this.skin = Skin3D(skinDef.bindShapeMatrix, skinDef.bones.map { it.toBone() })
}
},
skin = skinDef,
@@ -535,19 +534,20 @@ class ColladaParser {
}
fun Library3D.parseVisualScenes(xml: Xml) {
val instancesById = FastStringMap<Library3D.Instance3D>()
for (vscene in xml["library_visual_scenes"]["visual_scene"]) {
val scene = Library3D.Scene3D()
scene.id = vscene.str("id")
scene.name = vscene.str("name")
for (node in vscene["node"]) {
val instance = parseVisualSceneNode(node)
val instance = parseVisualSceneNode(node, instancesById)
scene.children += instance
}
scenes[scene.id] = scene
}
}
fun Library3D.parseVisualSceneNode(node: Xml): Library3D.Instance3D {
fun Library3D.parseVisualSceneNode(node: Xml, instancesById: FastStringMap<Library3D.Instance3D>): Library3D.Instance3D {
val instance = Library3D.Instance3D()
var location: Vector3D? = null
var scale: Vector3D? = null
@@ -559,6 +559,8 @@ class ColladaParser {
instance.name = node.str("name")
instance.type = node.str("type")
instancesById[instance.id] = instance
for (child in node.allNodeChildren) {
when (child.nameLC) {
"matrix" -> {
@@ -605,9 +607,18 @@ class ColladaParser {
instance.def = geometryDefs[geometryId]
}
"node" -> {
val childInstance = parseVisualSceneNode(child)
val childInstance = parseVisualSceneNode(child, instancesById)
instance.children.add(childInstance)
}
"instance_controller" -> {
val skinId = child.str("url").trim('#')
val skeletonId = child["skeleton"].firstText?.trim('#') ?: ""
val skin = skinDefs[skinId]
val skeleton = instancesById[skeletonId]
instance.def = geometryDefs[skin?.skinSource ?: ""]
instance.skin = skin
instance.skeleton = skeleton
}
"extra" -> {
}
else -> {

View File

@@ -15,7 +15,7 @@ data class Library3D(
val effectDefs: FastStringMap<EffectDef> = FastStringMap(),
val imageDefs: FastStringMap<ImageDef> = FastStringMap(),
val geometryDefs: FastStringMap<GeometryDef> = FastStringMap(),
val skins: FastStringMap<ColladaParser.Skin> = FastStringMap()
val skinDefs: FastStringMap<ColladaParser.Skin> = FastStringMap()
) {
suspend fun loadTextures() {
@@ -45,6 +45,8 @@ data class Library3D(
var id: String = ""
var name: String = ""
var type: String = ""
var skin: ColladaParser.Skin? = null
var skeleton: Instance3D? = null
}
open class Scene3D : Instance3D() {
@@ -96,8 +98,8 @@ data class Library3D(
val material: MaterialDef? = null
) : ObjectDef()
data class BoneDef(val name: String, val pose: Matrix3D) : Def() {
fun toBone() = Bone3D(name, pose.clone())
data class BoneDef(val name: String, val invBindMatrix: Matrix3D) : Def() {
fun toBone() = Bone3D(name, invBindMatrix.clone())
}
data class SkinDef(
@@ -125,7 +127,7 @@ fun Library3D.Instance3D.instantiate(): View3D {
}
}
is Library3D.GeometryDef -> {
ViewWithMesh3D(def.mesh)
ViewWithMesh3D(def.mesh, this.skeleton?.instantiate())
}
is Library3D.PerspectiveCameraDef -> {
Camera3D.Perspective(def.xfov, def.zmin, def.zmax)

View File

@@ -15,8 +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>) = Demo1.main()
//suspend fun main(args: Array<String>) = Demo3.main()
suspend fun main(args: Array<String>) = Demo1.main()
object Demo1 {
@JvmStatic
@@ -145,12 +145,12 @@ object Demo3 {
//val library = resourcesVfs["scene.dae"].readColladaLibrary()
//val library = resourcesVfs["cilinder.dae"].readColladaLibrary()
val library = resourcesVfs["box_textured.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_two_camera.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()
@@ -172,8 +172,8 @@ object Demo3 {
val mainSceneView = library.mainScene.instantiate()
val cameras = mainSceneView.findByType<Camera3D>()
val camera1 = cameras.first()
val camera2 = cameras.last()
val camera1 = cameras.firstOrNull() ?: camera
val camera2 = cameras.lastOrNull() ?: camera
//ambientColor = Colors.RED
//ambientColor = Colors.WHITE
@@ -191,25 +191,27 @@ object Demo3 {
}
*/
/*
var tick = 0
addUpdatable {
val angle = (tick / 1.0).degrees
camera.positionLookingAt(
cos(angle * 1) * 6, 2.0, -sin(angle * 1) * 6, // Orbiting camera
//1, 0, 4,
0, 0, 0
)
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)
if (camera1 == camera2) {
var tick = 0
val camera1Len = camera.localTransform.translation.length3
addUpdatable {
val angle = (tick / 1.0).degrees
camera.positionLookingAt(
cos(angle * 1) * camera1Len, 2.0, -sin(angle * 1) * camera1Len, // Orbiting camera
//1, 0, 4,
0, 0, 0
)
tick++
}
} else {
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)
}
}
}
}