Fix null pointer exceptions in GltfScene
This commit is contained in:
@@ -28,7 +28,7 @@ data class GltfAsset(val generator: String?, val version: String?)
|
|||||||
|
|
||||||
data class GltfScene(val nodes: IntArray)
|
data class GltfScene(val nodes: IntArray)
|
||||||
|
|
||||||
data class GltfNode(val name: String,
|
data class GltfNode(val name: String?,
|
||||||
val children: IntArray?,
|
val children: IntArray?,
|
||||||
val matrix: DoubleArray?,
|
val matrix: DoubleArray?,
|
||||||
val scale: DoubleArray?,
|
val scale: DoubleArray?,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class SceneAnimation(var channels: List<AnimationChannel>) {
|
|||||||
get() {
|
get() {
|
||||||
return channels.maxByOrNull { it.duration }?.duration ?: 0.0
|
return channels.maxByOrNull { it.duration }?.duration ?: 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyToTargets(input: Double) {
|
fun applyToTargets(input: Double) {
|
||||||
for (channel in channels) {
|
for (channel in channels) {
|
||||||
channel.applyToTarget(input)
|
channel.applyToTarget(input)
|
||||||
@@ -32,8 +33,10 @@ sealed class AnimationChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class QuaternionChannel(val target: KMutableProperty0<Quaternion>,
|
class QuaternionChannel(
|
||||||
val keyframer: KeyframerChannelQuaternion) : AnimationChannel() {
|
val target: KMutableProperty0<Quaternion>,
|
||||||
|
val keyframer: KeyframerChannelQuaternion
|
||||||
|
) : AnimationChannel() {
|
||||||
override fun applyToTarget(input: Double) {
|
override fun applyToTarget(input: Double) {
|
||||||
target.set(keyframer.value(input) ?: Quaternion.IDENTITY)
|
target.set(keyframer.value(input) ?: Quaternion.IDENTITY)
|
||||||
}
|
}
|
||||||
@@ -42,8 +45,10 @@ class QuaternionChannel(val target: KMutableProperty0<Quaternion>,
|
|||||||
get() = keyframer.duration()
|
get() = keyframer.duration()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Vector3Channel(val target: KMutableProperty0<Vector3>,
|
class Vector3Channel(
|
||||||
val keyframer: KeyframerChannelVector3, val default: Vector3) : AnimationChannel() {
|
val target: KMutableProperty0<Vector3>,
|
||||||
|
val keyframer: KeyframerChannelVector3, val default: Vector3
|
||||||
|
) : AnimationChannel() {
|
||||||
override fun applyToTarget(input: Double) {
|
override fun applyToTarget(input: Double) {
|
||||||
target.set(keyframer.value(input) ?: default)
|
target.set(keyframer.value(input) ?: default)
|
||||||
}
|
}
|
||||||
@@ -127,7 +132,10 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
||||||
cb.wrapU = WrapMode.REPEAT
|
cb.wrapU = WrapMode.REPEAT
|
||||||
cb.wrapV = WrapMode.REPEAT
|
cb.wrapV = WrapMode.REPEAT
|
||||||
val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.COLOR)
|
val sceneTexture = Texture(
|
||||||
|
ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"),
|
||||||
|
TextureTarget.COLOR
|
||||||
|
)
|
||||||
material.textures.add(sceneTexture)
|
material.textures.add(sceneTexture)
|
||||||
}
|
}
|
||||||
pbr.metallicRoughnessTexture?.let { texture ->
|
pbr.metallicRoughnessTexture?.let { texture ->
|
||||||
@@ -135,7 +143,10 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
||||||
cb.wrapU = WrapMode.REPEAT
|
cb.wrapU = WrapMode.REPEAT
|
||||||
cb.wrapV = WrapMode.REPEAT
|
cb.wrapV = WrapMode.REPEAT
|
||||||
val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.METALNESS_ROUGHNESS)
|
val sceneTexture = Texture(
|
||||||
|
ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"),
|
||||||
|
TextureTarget.METALNESS_ROUGHNESS
|
||||||
|
)
|
||||||
material.textures.add(sceneTexture)
|
material.textures.add(sceneTexture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,7 +156,10 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
||||||
cb.wrapU = WrapMode.REPEAT
|
cb.wrapU = WrapMode.REPEAT
|
||||||
cb.wrapV = WrapMode.REPEAT
|
cb.wrapV = WrapMode.REPEAT
|
||||||
val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.AMBIENT_OCCLUSION)
|
val sceneTexture = Texture(
|
||||||
|
ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"),
|
||||||
|
TextureTarget.AMBIENT_OCCLUSION
|
||||||
|
)
|
||||||
material.textures.add(sceneTexture)
|
material.textures.add(sceneTexture)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +169,13 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
cb.wrapU = WrapMode.REPEAT
|
cb.wrapU = WrapMode.REPEAT
|
||||||
cb.wrapV = WrapMode.REPEAT
|
cb.wrapV = WrapMode.REPEAT
|
||||||
|
|
||||||
val sceneTexture = Texture(ModelCoordinates(texture = cb, tangentInput = "va_tangent", pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.NORMAL)
|
val sceneTexture = Texture(
|
||||||
|
ModelCoordinates(
|
||||||
|
texture = cb,
|
||||||
|
tangentInput = "va_tangent",
|
||||||
|
pre = "x_texCoord.y = 1.0-x_texCoord.y;"
|
||||||
|
), TextureTarget.NORMAL
|
||||||
|
)
|
||||||
material.textures.add(sceneTexture)
|
material.textures.add(sceneTexture)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +185,10 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
|
|
||||||
emissiveTexture?.let {
|
emissiveTexture?.let {
|
||||||
val cb = images!![textures!![it.index].source].createSceneImage()
|
val cb = images!![textures!![it.index].source].createSceneImage()
|
||||||
val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.EMISSION)
|
val sceneTexture = Texture(
|
||||||
|
ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"),
|
||||||
|
TextureTarget.EMISSION
|
||||||
|
)
|
||||||
material.textures.add(sceneTexture)
|
material.textures.add(sceneTexture)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +202,10 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
||||||
cb.wrapU = WrapMode.REPEAT
|
cb.wrapU = WrapMode.REPEAT
|
||||||
cb.wrapV = WrapMode.REPEAT
|
cb.wrapV = WrapMode.REPEAT
|
||||||
val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.COLOR)
|
val sceneTexture = Texture(
|
||||||
|
ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"),
|
||||||
|
TextureTarget.COLOR
|
||||||
|
)
|
||||||
material.textures.add(sceneTexture)
|
material.textures.add(sceneTexture)
|
||||||
}
|
}
|
||||||
occlusionTexture?.let { texture ->
|
occlusionTexture?.let { texture ->
|
||||||
@@ -187,7 +213,10 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
||||||
cb.wrapU = WrapMode.REPEAT
|
cb.wrapU = WrapMode.REPEAT
|
||||||
cb.wrapV = WrapMode.REPEAT
|
cb.wrapV = WrapMode.REPEAT
|
||||||
val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.AMBIENT_OCCLUSION)
|
val sceneTexture = Texture(
|
||||||
|
ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"),
|
||||||
|
TextureTarget.AMBIENT_OCCLUSION
|
||||||
|
)
|
||||||
material.textures.add(sceneTexture)
|
material.textures.add(sceneTexture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,12 +230,14 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
|
|
||||||
fun GltfPrimitive.createScenePrimitive(): MeshPrimitive {
|
fun GltfPrimitive.createScenePrimitive(): MeshPrimitive {
|
||||||
val drawCommand = createDrawCommand(this@buildSceneNodes)
|
val drawCommand = createDrawCommand(this@buildSceneNodes)
|
||||||
val geometry = Geometry(listOf(drawCommand.vertexBuffer),
|
val geometry = Geometry(
|
||||||
|
listOf(drawCommand.vertexBuffer),
|
||||||
drawCommand.indexBuffer,
|
drawCommand.indexBuffer,
|
||||||
drawCommand.primitive,
|
drawCommand.primitive,
|
||||||
0,
|
0,
|
||||||
drawCommand.vertexCount)
|
drawCommand.vertexCount
|
||||||
val material = materials?.getOrNull(material)?.createSceneMaterial() ?: PBRMaterial()
|
)
|
||||||
|
val material = materials.getOrNull(material)?.createSceneMaterial() ?: PBRMaterial()
|
||||||
return MeshPrimitive(geometry, material)
|
return MeshPrimitive(geometry, material)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +245,7 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
val sceneNodes = mutableMapOf<GltfNode, SceneNode>()
|
val sceneNodes = mutableMapOf<GltfNode, SceneNode>()
|
||||||
fun GltfNode.createSceneNode(): SceneNode = sceneNodes.getOrPut(this) {
|
fun GltfNode.createSceneNode(): SceneNode = sceneNodes.getOrPut(this) {
|
||||||
val node = GltfSceneNode()
|
val node = GltfSceneNode()
|
||||||
node.name = name ?: ""
|
node.name = name ?: "no name"
|
||||||
node.translation = translation?.let { Vector3(it[0], it[1], it[2]) } ?: Vector3.ZERO
|
node.translation = translation?.let { Vector3(it[0], it[1], it[2]) } ?: Vector3.ZERO
|
||||||
node.scale = scale?.let { Vector3(it[0], it[1], it[2]) } ?: Vector3.ONE
|
node.scale = scale?.let { Vector3(it[0], it[1], it[2]) } ?: Vector3.ONE
|
||||||
node.rotation = rotation?.let { Quaternion(it[0], it[1], it[2], it[3]) } ?: Quaternion.IDENTITY
|
node.rotation = rotation?.let { Quaternion(it[0], it[1], it[2], it[3]) } ?: Quaternion.IDENTITY
|
||||||
@@ -223,7 +254,8 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
node.transform = Matrix44.fromDoubleArray(it).transposed
|
node.transform = Matrix44.fromDoubleArray(it).transposed
|
||||||
}
|
}
|
||||||
for (child in children.orEmpty) {
|
for (child in children.orEmpty) {
|
||||||
node.children.add(nodes[child].createSceneNode())
|
val childNode = nodes.getOrNull(child) ?: error("child node not found: $child")
|
||||||
|
node.children.add(childNode.createSceneNode())
|
||||||
}
|
}
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
@@ -286,7 +318,8 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
|
|
||||||
val scenes = scenes.map { scene ->
|
val scenes = scenes.map { scene ->
|
||||||
scene.nodes.map { node ->
|
scene.nodes.map { node ->
|
||||||
val gltfNode = nodes[node]
|
val gltfNode = nodes.getOrNull(node) ?: error("node not found: $node")
|
||||||
|
require(gltfNode != null)
|
||||||
val sceneNode = gltfNode.createSceneNode()
|
val sceneNode = gltfNode.createSceneNode()
|
||||||
sceneNode
|
sceneNode
|
||||||
}
|
}
|
||||||
@@ -369,7 +402,8 @@ fun GltfFile.buildSceneNodes(): GltfSceneData {
|
|||||||
val outputZ = outputData.getFloat(outputOffset + i * outputStride + 8).toDouble()
|
val outputZ = outputData.getFloat(outputOffset + i * outputStride + 8).toDouble()
|
||||||
keyframer.add(input, Vector3(outputX, outputY, outputZ))
|
keyframer.add(input, Vector3(outputX, outputY, outputZ))
|
||||||
}
|
}
|
||||||
val target = if (channel.target.path == "translation") sceneNode::translation else sceneNode::scale
|
val target =
|
||||||
|
if (channel.target.path == "translation") sceneNode::translation else sceneNode::scale
|
||||||
val default = if (channel.target.path == "translation") Vector3.ZERO else Vector3.ONE
|
val default = if (channel.target.path == "translation") Vector3.ZERO else Vector3.ONE
|
||||||
Vector3Channel(target, keyframer, default)
|
Vector3Channel(target, keyframer, default)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user