Advertisement
Akucuki

LibGDX drawing on a 3D object testure sample

Mar 17th, 2023 (edited)
192
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 10.07 KB | Source Code | 0 0
  1. // assets - https://drive.google.com/drive/folders/1zilT9cpxLEIVAaXQ0TzFLjllf0Lcma4Z?usp=sharing
  2.  
  3. data class ModelTriangle(
  4.     val v1: Vector3,
  5.     val v2: Vector3,
  6.     val v3: Vector3,
  7.     val uvs: Array<Vector2>
  8. ) {
  9.     override fun equals(other: Any?): Boolean {
  10.         if (this === other) return true
  11.         if (javaClass != other?.javaClass) return false
  12.  
  13.         other as ModelTriangle
  14.  
  15.         if (v1 != other.v1) return false
  16.         if (v2 != other.v2) return false
  17.         if (v3 != other.v3) return false
  18.         if (!uvs.contentEquals(other.uvs)) return false
  19.  
  20.         return true
  21.     }
  22.  
  23.     override fun hashCode(): Int {
  24.         var result = v1.hashCode()
  25.         result = 31 * result + v2.hashCode()
  26.         result = 31 * result + v3.hashCode()
  27.         result = 31 * result + uvs.contentHashCode()
  28.         return result
  29.     }
  30. }
  31.  
  32. class SkinEditorGame : ApplicationAdapter() {
  33.  
  34.     private var modelBatch: ModelBatch? = null
  35.     private lateinit var environment: Environment
  36.     private lateinit var cam: Camera
  37.     private var instance: ModelInstance? = null
  38.     private lateinit var camController: CameraInputController
  39.     private lateinit var assets: AssetManager
  40.     private var loading: Boolean = false
  41.     private var spriteBatch: SpriteBatch? = null
  42.     private var backgroundTexture: Texture? = null
  43.  
  44.     override fun create() {
  45.         spriteBatch = SpriteBatch()
  46.         modelBatch = ModelBatch()
  47.         environment = Environment()
  48.         environment.set(ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f))
  49.         // Left and right
  50.         environment.add(DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f))
  51.         environment.add(DirectionalLight().set(0.8f, 0.8f, 0.8f, 1f, -0.8f, 0.2f))
  52.  
  53.         // Facing and back
  54.         environment.add(DirectionalLight().set(0.8f, 0.8f, 0.8f, 0f, -0.8f, -1f))
  55.         environment.add(DirectionalLight().set(0.8f, 0.8f, 0.8f, 0f, -0.8f, 1f))
  56.  
  57.         // Bottom
  58.         environment.add(DirectionalLight().set(0.8f, 0.8f, 0.8f, 0f, 1f, 0f))
  59.  
  60.         backgroundTexture = Texture("bg_main.png")
  61.  
  62.         cam = PerspectiveCamera(60f, Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat())
  63.         cam.position.set(0f, 1f, -4f)
  64.         cam.lookAt(0f, 1f, 0f)
  65.         cam.near = 1f
  66.         cam.far = 10f
  67.         cam.update()
  68.  
  69.         camController = CameraInputController(cam)
  70.         Gdx.input.inputProcessor = camController
  71.  
  72.         assets = AssetManager()
  73.  
  74.         val parameter = TextureLoader.TextureParameter()
  75.         parameter.minFilter = Texture.TextureFilter.Nearest
  76.         parameter.magFilter = Texture.TextureFilter.Nearest
  77.         parameter.genMipMaps = false
  78.  
  79.  
  80.         assets.load("Grass_Block.g3dj", Model::class.java)
  81.         assets.load("Grass_Block_TEX.png", Texture::class.java, parameter)
  82.  
  83.         loading = true
  84.     }
  85.  
  86.     private fun doneLoading() {
  87.         val skinModel = assets.get("Grass_Block.g3dj", Model::class.java)
  88.         val texture = assets.get("Grass_Block_TEX.png", Texture::class.java)
  89.         instance = ModelInstance(skinModel)
  90.  
  91.         instance!!.materials.first().set(TextureAttribute.createDiffuse(texture))
  92.         loading = false
  93.     }
  94.  
  95.     override fun render() {
  96.         if (loading && assets.update()) doneLoading()
  97.         camController.update()
  98.  
  99.         Gdx.gl.glViewport(0, 0, Gdx.graphics.width, Gdx.graphics.height)
  100.         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT or GL20.GL_DEPTH_BUFFER_BIT)
  101.  
  102.         spriteBatch?.begin()
  103.         spriteBatch?.draw(
  104.             backgroundTexture,
  105.             0f,
  106.             0f,
  107.             Gdx.graphics.width.toFloat(),
  108.             Gdx.graphics.height.toFloat()
  109.         )
  110.         spriteBatch?.end()
  111.  
  112.         modelBatch?.begin(cam)
  113.         instance?.let { modelBatch?.render(it, environment) }
  114.         modelBatch?.end()
  115.  
  116.         if (Gdx.input.isTouched) {
  117.  
  118.             val ray = cam.getPickRay(Gdx.input.x.toFloat(), Gdx.input.y.toFloat())
  119.  
  120.             val meshPart = instance!!.model.meshParts[0]
  121.  
  122.             val numVertices = meshPart.mesh.numVertices
  123.             val vertexSize = meshPart.mesh.vertexSize / 4
  124.             val vertices = FloatArray(numVertices * vertexSize)
  125.             meshPart.mesh.getVertices(0, vertices.size, vertices)
  126.  
  127.             val indices = ShortArray(meshPart.mesh.numIndices)
  128.             meshPart.mesh.getIndices(indices)
  129.  
  130.             println("Vertices: ${vertices.asList()}")
  131.             println("Vertex size: $vertexSize")
  132.             println("Num vertices: $numVertices")
  133.             println("Indices: ${indices.asList()}")
  134.  
  135.             val triangles = mutableListOf<ModelTriangle>()
  136.             for (i in indices.indices step 3) {
  137.                 val stride = meshPart.mesh.vertexSize / 4
  138.                 val vertexIndex1 = indices[i].toInt() * stride
  139.                 val vertexIndex2 = indices[i + 1].toInt() * stride
  140.                 val vertexIndex3 = indices[i + 2].toInt() * stride
  141.  
  142.                 val vertex1 = Vector3(
  143.                     vertices[vertexIndex1],
  144.                     vertices[vertexIndex1 + 1],
  145.                     vertices[vertexIndex1 + 2]
  146.                 )
  147.                 val vertex2 = Vector3(
  148.                     vertices[vertexIndex2],
  149.                     vertices[vertexIndex2 + 1],
  150.                     vertices[vertexIndex2 + 2]
  151.                 )
  152.                 val vertex3 = Vector3(
  153.                     vertices[vertexIndex3],
  154.                     vertices[vertexIndex3 + 1],
  155.                     vertices[vertexIndex3 + 2]
  156.                 )
  157.  
  158.                 val vertexAttributes = meshPart.mesh.vertexAttributes
  159.                 val uvOffset =
  160.                     vertexAttributes.findByUsage(VertexAttributes.Usage.TextureCoordinates).offset / 4
  161.  
  162.                 val uv1 = Vector2(
  163.                     vertices[vertexIndex1 + uvOffset],
  164.                     vertices[vertexIndex1 + uvOffset + 1]
  165.                 )
  166.                 val uv2 = Vector2(
  167.                     vertices[vertexIndex2 + uvOffset],
  168.                     vertices[vertexIndex2 + uvOffset + 1]
  169.                 )
  170.                 val uv3 = Vector2(
  171.                     vertices[vertexIndex3 + uvOffset],
  172.                     vertices[vertexIndex3 + uvOffset + 1]
  173.                 )
  174.  
  175.                 val uvs = arrayOf(uv1, uv2, uv3)
  176.  
  177.                 val triangle = ModelTriangle(vertex1, vertex2, vertex3, uvs)
  178.                 triangles.add(triangle)
  179.             }
  180.  
  181.             println("Triangles: $triangles")
  182.             println("Triangles size: ${triangles.size}")
  183.  
  184.             val intersectionPoint = Vector3()
  185.             val intersectionTriangle = triangles.find {
  186.                 Intersector.intersectRayTriangle(
  187.                     ray,
  188.                     it.v1,
  189.                     it.v2,
  190.                     it.v3,
  191.                     intersectionPoint
  192.                 )
  193.             }
  194.  
  195.             println("Intersection point: $intersectionPoint")
  196.             println("Is intersection found: ${intersectionTriangle != null}")
  197.  
  198.             intersectionTriangle?.let { triangle ->
  199.                 val instanceTexture =
  200.                     instance!!.materials.first().get(TextureAttribute.Diffuse) as TextureAttribute
  201.                 val uv = getIntersectionUV(intersectionPoint, triangle, triangle.uvs)
  202.                 val textureX = (uv.x * instanceTexture.textureDescription.texture.width).toInt()
  203.                 val textureY = (uv.y * instanceTexture.textureDescription.texture.height).toInt()
  204.  
  205.                 println("Texture coordinates: x: $textureX, y: $textureY")
  206.  
  207.                 val texturePixmap = textureToPixmap(instanceTexture.textureDescription.texture)
  208.                 drawPointOnPixmap(texturePixmap, textureX, textureY, Color.RED)
  209.                 val newTexture = Texture(texturePixmap)
  210.                 instance!!.materials.first().set(TextureAttribute.createDiffuse(newTexture))
  211.             }
  212.  
  213.         }
  214.     }
  215.  
  216.     private fun textureToPixmap(texture: Texture): Pixmap {
  217.         val textureData = texture.textureData
  218.         if (!textureData.isPrepared) {
  219.             textureData.prepare()
  220.         }
  221.         val pixmap = textureData.consumePixmap()
  222.         val pixmapCopy = Pixmap(pixmap.width, pixmap.height, pixmap.format)
  223.         pixmapCopy.drawPixmap(pixmap, 0, 0)
  224.         textureData.disposePixmap()
  225.  
  226.         return pixmapCopy
  227.     }
  228.  
  229.     private fun drawPointOnPixmap(pixmap: Pixmap, x: Int, y: Int, color: Color) {
  230.         pixmap.setColor(color)
  231.         pixmap.fillRectangle(x, y, 50, 50)
  232.     }
  233.  
  234.     private fun getIntersectionUV(
  235.         intersectionPoint: Vector3,
  236.         triangle: ModelTriangle,
  237.         uvs: Array<Vector2>
  238.     ): Vector2 {
  239.         val barycentricCoords = toBarycoord3D(
  240.             intersectionPoint, triangle.v1, triangle.v2, triangle.v3
  241.         )
  242.  
  243.         val isInsideTheTriangle = GeometryUtils.barycoordInsideTriangle(Vector2(barycentricCoords.x, barycentricCoords.y))
  244.         println("Is inside the triangle: $isInsideTheTriangle")
  245.  
  246.         val uv1 = uvs[0]
  247.         val uv2 = uvs[1]
  248.         val uv3 = uvs[2]
  249.  
  250.         return Vector2(
  251.             barycentricCoords.z * uv1.x + barycentricCoords.x * uv2.x + barycentricCoords.y * uv3.x,
  252.             barycentricCoords.z * uv1.y + barycentricCoords.x * uv2.y + barycentricCoords.y * uv3.y
  253.         )
  254.     }
  255.  
  256.     private fun toBarycoord3D(
  257.         point: Vector3,
  258.         a: Vector3,
  259.         b: Vector3,
  260.         c: Vector3,
  261.     ): Vector3 {
  262.         val v0 = Vector3().set(b).sub(a)
  263.         val v1 = Vector3().set(c).sub(a)
  264.         val v2 = Vector3().set(point).sub(a)
  265.  
  266.         val d00 = v0.dot(v0)
  267.         val d01 = v0.dot(v1)
  268.         val d11 = v1.dot(v1)
  269.         val d20 = v2.dot(v0)
  270.         val d21 = v2.dot(v1)
  271.  
  272.         val denom = d00 * d11 - d01 * d01
  273.         val barycentricOut = Vector3()
  274.         barycentricOut.x = (d11 * d20 - d01 * d21) / denom
  275.         barycentricOut.y = (d00 * d21 - d01 * d20) / denom
  276.         barycentricOut.z = 1.0f - barycentricOut.x - barycentricOut.y
  277.  
  278.         return barycentricOut
  279.     }
  280.  
  281.     override fun dispose() {
  282.         modelBatch?.dispose()
  283.         assets.dispose()
  284.     }
  285. }
Advertisement
Comments
  • Akucuki
    2 years
    Comment was deleted
Add Comment
Please, Sign In to add comment
Advertisement