SHARE
TWEET

Untitled

a guest Jul 22nd, 2019 54 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package ru.poopycoders.cavedefense.loader
  2.  
  3. import com.badlogic.gdx.assets.loaders.FileHandleResolver
  4. import com.badlogic.gdx.assets.loaders.ModelLoader
  5. import com.badlogic.gdx.files.FileHandle
  6. import com.badlogic.gdx.graphics.Color
  7. import com.badlogic.gdx.graphics.GL20
  8. import com.badlogic.gdx.graphics.VertexAttributes
  9. import com.badlogic.gdx.graphics.g3d.model.MeshPart
  10. import com.badlogic.gdx.graphics.g3d.model.data.*
  11. import com.badlogic.gdx.graphics.g3d.utils.MeshBuilder
  12. import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder
  13. import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.BoxShapeBuilder
  14. import com.badlogic.gdx.math.Matrix4
  15. import com.badlogic.gdx.math.Quaternion
  16. import com.badlogic.gdx.math.Vector2
  17. import com.badlogic.gdx.math.Vector3
  18. import com.badlogic.gdx.utils.ArrayMap
  19. import com.badlogic.gdx.utils.BaseJsonReader
  20. import com.badlogic.gdx.utils.JsonValue
  21.  
  22. class JsonModelLoader(val reader: BaseJsonReader, resolver: FileHandleResolver?) : ModelLoader<ModelLoader.ModelParameters>(resolver) {
  23.  
  24.     companion object {
  25.         private const val rawAttributes = VertexAttributes.Usage.Position.toLong() or VertexAttributes.Usage.Normal.toLong() or VertexAttributes.Usage.TextureCoordinates.toLong()
  26.         private const val primitiveType = GL20.GL_TRIANGLES
  27.     }
  28.  
  29.     val attributes = MeshBuilder.createAttributes(rawAttributes)
  30.  
  31.     override fun loadModelData(fileHandle: FileHandle, parameters: ModelParameters?): ModelData {
  32.         return parseModel(fileHandle)
  33.     }
  34.  
  35.     private fun parseModel(handle: FileHandle): ModelData {
  36.         val json = reader.parse(handle)
  37.         val model = ModelData()
  38.         model.id = "model"
  39.  
  40.         for (i in 0 until json.size) {
  41.             val tag = json[i]
  42.  
  43.             if (tag.name != "format_version") {
  44.                 parseGeometry(tag, model)
  45.                 break
  46.             }
  47.         }
  48.  
  49.         return model
  50.     }
  51.  
  52.     private fun parseGeometry(geometry: JsonValue, model: ModelData) {
  53.         val textureWidth = geometry.getInt("texturewidth")
  54.         val textureHeight = geometry.getInt("textureheight")
  55.  
  56.         val visibleBoundsWidth = geometry.getInt("visible_bounds_width")
  57.         val visibleBoundsHeight = geometry.getInt("visible_bounds_height")
  58.         val visibleBoundsOffset = Vector3(geometry.require("visible_bounds_offset").asFloatArray())
  59.  
  60.         val bonesJson = geometry.get("bones")
  61.  
  62.         // Parse bones
  63.         val bonesMap = HashMap<String, Bone>()
  64.         val bones = Array(bonesJson.size) {
  65.             parseBone(bonesJson[it]).apply {
  66.                 if (this.parent != null) {
  67.                     bonesMap[this.parent]!!.children.add(this)
  68.                 }
  69.  
  70.                 bonesMap[this.name] = this
  71.             }
  72.         }
  73.  
  74.         // Build nodes, root meshes and mesh parts
  75.         val nodesMap = HashMap<String, ModelNode>()
  76.  
  77.         for (bone in bones) {
  78.             if (bone.parent == null) {
  79.                 val node = bone.buildNode(nodesMap)
  80.                 model.nodes.add(node)
  81.  
  82.                 model.addMesh(bone.buildRootMesh(node))
  83.             }
  84.         }
  85.  
  86.         // Default material for all parts
  87.         model.materials.add(ModelMaterial().apply {
  88.             id = "default"
  89.  
  90.             ambient = Color(1f, 1f, 1f, 1f)
  91.             diffuse = Color(0.8f, 0.8f, 0.8f, 0.8f)
  92.             emissive = Color(0.8f, 0.8f, 0.8f, 0.8f)
  93.  
  94.             opacity = 1f
  95.             shininess = 0f
  96.  
  97.             textures = com.badlogic.gdx.utils.Array()
  98.         })
  99.  
  100.         // Test animation
  101.         model.animations.add(ModelAnimation().apply {
  102.             id = "test"
  103.  
  104.             nodeAnimations.add(ModelNodeAnimation().apply {
  105.                 nodeId = "head"
  106.                 rotation = com.badlogic.gdx.utils.Array<ModelNodeKeyframe<Quaternion>>(30)
  107.  
  108.                 for (i in 0 until 30) {
  109.                     rotation.insert(i, ModelNodeKeyframe<Quaternion>().apply {
  110.                         keytime = 1f / 30 * i
  111.                         value = Quaternion(Vector3.Y, 90 + 360f / 30 * i)
  112.                     })
  113.                 }
  114.             })
  115.         })
  116.     }
  117.  
  118.     private fun parseBone(bone: JsonValue): Bone {
  119.         val name = bone.getString("name")
  120.         val parent = bone.getString("parent", null)
  121.         val pivot = Vector3(bone.require("pivot").asFloatArray())
  122.         val rotation = if (bone.has("rotation")) Vector3(bone.require("rotation").asFloatArray()) else Vector3.Zero
  123.  
  124.         val cubesJson = if (bone.has("cubes")) bone.require("cubes") else null
  125.         val cubes = Array(cubesJson?.size ?: 0) {
  126.             val cube = cubesJson!![it]
  127.  
  128.             val origin = Vector3(cube.require("origin").asFloatArray())
  129.             val size = Vector3(cube.require("size").asFloatArray())
  130.             val uv = cube.require("uv").asFloatArray()
  131.             val inflate = if (cube.has("inflate")) cube.getFloat("inflate") else 0f
  132.  
  133.             Cube(origin, size, Vector2(uv[0], uv[1]), inflate)
  134.         }
  135.         return Bone(name, parent, pivot, rotation, cubes, ArrayList())
  136.     }
  137.  
  138.     inner class Bone(val name: String, val parent: String?, val pivot: Vector3, val rotation: Vector3, val cubes: Array<Cube>, var children: ArrayList<Bone>) {
  139.  
  140.         fun buildNode(nodesMap: HashMap<String, ModelNode>): ModelNode {
  141.             println("Build node: $name")
  142.             val node = ModelNode()
  143.             nodesMap[name] = node
  144.  
  145.             node.id = name
  146.             node.translation = Vector3.Zero
  147.             node.scale = Vector3(1.0f, 1.0f, 1.0f)
  148. //            node.rotation = Quaternion(rotation.x, rotation.y, rotation.z, 0.0f)
  149.             node.meshId = if (parent == null) name else nodesMap[parent]!!.meshId
  150.  
  151.             node.children = Array(children.size) {
  152.                 children[it].buildNode(nodesMap)
  153.             }
  154.  
  155.             return node
  156.         }
  157.  
  158.         fun buildRootMesh(rootNode: ModelNode): ModelMesh {
  159.             val mesh = ModelMesh()
  160.  
  161.             mesh.id = name
  162.             mesh.attributes = Array(attributes.size()) { attributes[it] }
  163.  
  164.             val builder = DirectMeshBuilder()
  165.             val rawParts = ArrayList<MeshPart>()
  166.  
  167.             builder.begin(rawAttributes)
  168.             buildMesh(rootNode, builder, rawParts, null) // build mesh of this part
  169.  
  170.             val (vertices, indices) = builder.endAndGetItems()
  171.             mesh.vertices = vertices
  172.  
  173.             mesh.parts = Array(rawParts.size) { // build meshes of child parts
  174.                 ModelMeshPart().apply {
  175.                     val rawPart = rawParts[it]
  176.  
  177.                     this.id = rawPart.id
  178.                     this.primitiveType = rawPart.primitiveType
  179.                     this.indices = indices.copyOfRange(rawPart.offset, rawPart.offset + rawPart.size)
  180.                 }
  181.             }
  182.  
  183.             return mesh
  184.         }
  185.  
  186.         fun buildMesh(node: ModelNode, builder: MeshBuilder, parts: ArrayList<MeshPart>, parent: ModelNode?) {
  187.             if (cubes.isNotEmpty()) {
  188.                 val part = builder.part(name, primitiveType)
  189.  
  190.                 for (cube in cubes) {
  191.                     val origin = cube.origin.mulAdd(cube.size, 0.5f)
  192.                     val size = cube.size
  193.  
  194.                     BoxShapeBuilder.build(builder, origin.x, origin.y, origin.z, size.x, size.y, size.z)
  195.                 }
  196.  
  197.                 node.parts = arrayOf(ModelNodePart().apply {
  198.                     materialId = "default"
  199.                     meshPartId = part.id
  200.                     bones = ArrayMap(1)
  201.  
  202.                     if(parent != null){
  203.                         bones.put(parent.id, Matrix4())
  204.                     }
  205.  
  206. //                    uvMapping = Array(2) {
  207. //                        IntArray(2) // later
  208. //                    }
  209.                 })
  210.  
  211.                 parts.add(part)
  212.             } else {
  213.                 node.parts = arrayOf()
  214.             }
  215.  
  216.             for ((i, child) in children.withIndex()) {
  217.                 child.buildMesh(node.children[i], builder, parts, node)
  218.             }
  219.         }
  220.     }
  221.  
  222.     data class Cube(val origin: Vector3, val size: Vector3, val uv: Vector2, val inflate: Float)
  223.  
  224.     class DirectMeshBuilder : MeshBuilder() {
  225.  
  226.         private val vertTmp1 = MeshPartBuilder.VertexInfo()
  227.         private val vertTmp2 = MeshPartBuilder.VertexInfo()
  228.         private val vertTmp3 = MeshPartBuilder.VertexInfo()
  229.         private val vertTmp4 = MeshPartBuilder.VertexInfo()
  230.  
  231.         fun endAndGetItems(): Pair<FloatArray, ShortArray> {
  232.             part("mesh_end", GL20.GL_TRIANGLES)
  233.             return Pair(vertices!!, indices!!)
  234.         }
  235.  
  236.         override fun rect(corner00: Vector3?, corner10: Vector3?, corner11: Vector3?, corner01: Vector3?, normal: Vector3?) {
  237.             rect(vertTmp1.set(corner00, normal, null, null).setUV(0f, 1f), vertTmp2.set(corner10, normal, null, null).setUV(1f, 1f),
  238.                     vertTmp3.set(corner11, normal, null, null).setUV(1f, 0f), vertTmp4.set(corner01, normal, null, null).setUV(0f, 0f))
  239.         }
  240.  
  241.     }
  242. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top