IDE perf tests for K/N: Produce duplicated *.kt files on demand

This commit is contained in:
Dmitriy Dolovov
2020-03-04 19:41:10 +07:00
parent 44c8a85241
commit 17152899ac
16 changed files with 54 additions and 934 deletions
@@ -61,6 +61,7 @@ class PerformanceNativeProjectsTest : AbstractPerformanceProjectsTest() {
private enum class TestProject(
val templateName: String,
val duplicatesAmount: Int = 2,
val filesToHighlight: List<String>
) {
HELLO_WORLD(
@@ -85,6 +86,7 @@ class PerformanceNativeProjectsTest : AbstractPerformanceProjectsTest() {
init {
assertTrue(filesToHighlight.isNotEmpty())
assertTrue(duplicatesAmount in 0..100)
}
}
@@ -230,6 +232,44 @@ class PerformanceNativeProjectsTest : AbstractPerformanceProjectsTest() {
fail("Some files have not been merged in project root directory: $projectRoot: ${unmergedFiles.joinToString()}")
}
// produce N duplicates of *.kt files inside the project root
if (testProject.duplicatesAmount > 0) {
val originalKtFiles = projectRoot.walkTopDown()
.filter { it.isFile && it.name.endsWith(".kt") }
.toList()
for (originalKtFile in originalKtFiles) {
val originalKtFileContents = originalKtFile.readLines()
assertTrue(
"$originalKtFile must have @file:Suppress(\"PackageDirectoryMismatch\") annotation",
originalKtFileContents.any { it.startsWith("@file:Suppress") && it.contains("\"PackageDirectoryMismatch\"") }
)
val packageLineIndex = originalKtFileContents.indexOfFirst { it.startsWith("package perfTestPackage1") }
assertTrue(
"$originalKtFile must have package declaration: package perfTestPackage1",
packageLineIndex != -1
)
for (i in 1..testProject.duplicatesAmount) {
val n = i + 1
val duplicateKtFile = originalKtFile.resolveSibling("${originalKtFile.nameWithoutExtension}$n.kt")
duplicateKtFile.writeText(
buildString {
originalKtFileContents.forEachIndexed { index, line ->
if (index == packageLineIndex) {
appendln(line.replace("perfTestPackage1", "perfTestPackage$n"))
} else {
appendln(line)
}
}
}
)
}
}
}
// check all necessary files are there
listOf("build.gradle.kts", "settings.gradle.kts", "gradle.properties")
.filter { !projectRoot.resolve(it).exists() }
@@ -1,8 +1,11 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package perfTestPackage1 // this package is mandatory
import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.memScoped
@@ -1,77 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.toKString
import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType
import kotlinx.cli.required
import platform.posix.fclose
import platform.posix.fgets
import platform.posix.fopen
import platform.posix.perror
import kotlin.collections.set
private fun parseLine(line: String, separator: Char) : List<String> {
val result = mutableListOf<String>()
val builder = StringBuilder()
var quotes = 0
for (ch in line) {
when {
ch == '\"' -> {
quotes++
builder.append(ch)
}
(ch == '\n') || (ch == '\r') -> {}
(ch == separator) && (quotes % 2 == 0) -> {
result.add(builder.toString())
builder.setLength(0)
}
else -> builder.append(ch)
}
}
return result
}
fun main(args: Array<String>) {
val argParser = ArgParser("csvparser")
val fileName by argParser.argument(ArgType.String, description = "CSV file")
val column by argParser.option(ArgType.Int, description = "Column to parse").required()
val count by argParser.option(ArgType.Int, description = "Count of lines to parse").required()
argParser.parse(args)
val file = fopen(fileName, "r")
if (file == null) {
perror("cannot open input file $fileName")
return
}
val keyValue = mutableMapOf<String, Int>()
try {
memScoped {
val bufferLength = 64 * 1024
val buffer = allocArray<ByteVar>(bufferLength)
for (i in 1..count) {
val nextLine = fgets(buffer, bufferLength, file)?.toKString()
if (nextLine == null || nextLine.isEmpty()) break
val records = parseLine(nextLine, ',')
val key = records[column]
val current = keyValue[key] ?: 0
keyValue[key] = current + 1
}
}
} finally {
fclose(file)
}
keyValue.forEach {
println("${it.key} -> ${it.value}")
}
}
@@ -1,77 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.toKString
import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType
import kotlinx.cli.required
import platform.posix.fclose
import platform.posix.fgets
import platform.posix.fopen
import platform.posix.perror
import kotlin.collections.set
private fun parseLine(line: String, separator: Char) : List<String> {
val result = mutableListOf<String>()
val builder = StringBuilder()
var quotes = 0
for (ch in line) {
when {
ch == '\"' -> {
quotes++
builder.append(ch)
}
(ch == '\n') || (ch == '\r') -> {}
(ch == separator) && (quotes % 2 == 0) -> {
result.add(builder.toString())
builder.setLength(0)
}
else -> builder.append(ch)
}
}
return result
}
fun main(args: Array<String>) {
val argParser = ArgParser("csvparser")
val fileName by argParser.argument(ArgType.String, description = "CSV file")
val column by argParser.option(ArgType.Int, description = "Column to parse").required()
val count by argParser.option(ArgType.Int, description = "Count of lines to parse").required()
argParser.parse(args)
val file = fopen(fileName, "r")
if (file == null) {
perror("cannot open input file $fileName")
return
}
val keyValue = mutableMapOf<String, Int>()
try {
memScoped {
val bufferLength = 64 * 1024
val buffer = allocArray<ByteVar>(bufferLength)
for (i in 1..count) {
val nextLine = fgets(buffer, bufferLength, file)?.toKString()
if (nextLine == null || nextLine.isEmpty()) break
val records = parseLine(nextLine, ',')
val key = records[column]
val current = keyValue[key] ?: 0
keyValue[key] = current + 1
}
}
} finally {
fclose(file)
}
keyValue.forEach {
println("${it.key} -> ${it.value}")
}
}
@@ -1,3 +1,5 @@
@file:Suppress("PackageDirectoryMismatch")
package perfTestPackage1 // this package is mandatory
fun main(args: Array<String>) {
println("Hello World!")
@@ -1,4 +0,0 @@
fun main(args: Array<String>) {
println("Hello World!")
}
@@ -1,4 +0,0 @@
fun main(args: Array<String>) {
println("Hello World!")
}
@@ -1,3 +1,6 @@
@file:Suppress("PackageDirectoryMismatch")
package perfTestPackage1 // this package is mandatory
import kotlin.test.Test
import kotlin.test.assertTrue
@@ -1,11 +0,0 @@
import kotlin.test.Test
import kotlin.test.assertTrue
private const val GREETING = "Hello, Kotlin/Native!"
class HelloTest2 {
@Test
fun testHello() {
assertTrue("Kotlin/Native" in GREETING)
}
}
@@ -1,11 +0,0 @@
import kotlin.test.Test
import kotlin.test.assertTrue
private const val GREETING = "Hello, Kotlin/Native!"
class HelloTest3 {
@Test
fun testHello() {
assertTrue("Kotlin/Native" in GREETING)
}
}
+2 -1
View File
@@ -3,7 +3,8 @@
* that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
@file:Suppress("PackageDirectoryMismatch", "RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
package perfTestPackage1 // this package is mandatory
import kotlinx.cinterop.FloatVar
import kotlinx.cinterop.allocArray
-234
View File
@@ -1,234 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
import kotlinx.cinterop.FloatVar
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.cValuesOf
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.set
import kotlinx.cinterop.toCValues
import platform.gles.GL_COLOR_BUFFER_BIT
import platform.gles.GL_CULL_FACE
import platform.gles.GL_CW
import platform.gles.GL_DEPTH_BUFFER_BIT
import platform.gles.GL_DEPTH_TEST
import platform.gles.GL_DIFFUSE
import platform.gles.GL_DITHER
import platform.gles.GL_FASTEST
import platform.gles.GL_FLOAT
import platform.gles.GL_FRONT_AND_BACK
import platform.gles.GL_LIGHT0
import platform.gles.GL_LIGHTING
import platform.gles.GL_MODELVIEW
import platform.gles.GL_NORMAL_ARRAY
import platform.gles.GL_PERSPECTIVE_CORRECTION_HINT
import platform.gles.GL_POSITION
import platform.gles.GL_PROJECTION
import platform.gles.GL_SHININESS
import platform.gles.GL_SMOOTH
import platform.gles.GL_SPECULAR
import platform.gles.GL_TEXTURE_2D
import platform.gles.GL_TEXTURE_COORD_ARRAY
import platform.gles.GL_TRIANGLES
import platform.gles.GL_UNSIGNED_BYTE
import platform.gles.GL_VERTEX_ARRAY
import platform.gles.glClear
import platform.gles.glClearColor
import platform.gles.glDisable
import platform.gles.glDrawElements
import platform.gles.glEnable
import platform.gles.glEnableClientState
import platform.gles.glFrontFace
import platform.gles.glFrustumf
import platform.gles.glHint
import platform.gles.glLightfv
import platform.gles.glLoadIdentity
import platform.gles.glMaterialf
import platform.gles.glMaterialfv
import platform.gles.glMatrixMode
import platform.gles.glMultMatrixf
import platform.gles.glNormalPointer
import platform.gles.glPopMatrix
import platform.gles.glPushMatrix
import platform.gles.glShadeModel
import platform.gles.glTexCoordPointer
import platform.gles.glTranslatef
import platform.gles.glVertexPointer
import platform.gles.glViewport
import platform.posix.sqrtf
private const val WIDTH = 600
private const val HEIGHT = 800
private const val SCALE = 1.25f
fun main() = memScoped {
glDisable(GL_DITHER)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)
glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
glEnable(GL_CULL_FACE)
glShadeModel(GL_SMOOTH)
glEnable(GL_DEPTH_TEST)
glViewport(0, 0, WIDTH, HEIGHT)
val ratio = WIDTH.toFloat() / HEIGHT
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0.0f, 0.0f, -2.0f)
glLightfv(GL_LIGHT0, GL_POSITION, cValuesOf(1.25f, 1.25f, -2.0f, 0.0f))
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_TEXTURE_2D)
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, cValuesOf(0.0f, 1.0f, 1.0f, 1.0f))
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, cValuesOf(0.3f, 0.3f, 0.3f, 1.0f))
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0f)
glPushMatrix()
glMatrixMode(GL_MODELVIEW)
val matrix = allocArray<FloatVar>(16)
for (i in 0..3)
for (j in 0..3)
matrix[i * 4 + j] = if (i == j) 1.0f else 0.0f
glMultMatrixf(matrix)
glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).toUInt())
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
val polygon = RegularPolyhedra.Dodecahedron
val vertices = mutableListOf<Float>()
val texCoords = mutableListOf<Float>()
val triangles = mutableListOf<Byte>()
val normals = mutableListOf<Float>()
val texturePoints = arrayOf(Vector2(0.0f, 0.2f), Vector2(0.0f, 0.8f), Vector2(0.6f, 1.0f), Vector2(1.0f, 0.5f), Vector2(0.8f, 0.0f))
for (face in polygon.faces) {
val u = polygon.vertices[face[2].toInt()] - polygon.vertices[face[1].toInt()]
val v = polygon.vertices[face[0].toInt()] - polygon.vertices[face[1].toInt()]
val normal = u.crossProduct(v).normalized()
val copiedFace = ByteArray(face.size)
for (j in face.indices) {
copiedFace[j] = (vertices.size / 4).toByte()
polygon.vertices[face[j].toInt()].copyCoordinatesTo(vertices)
vertices.add(SCALE)
normal.copyCoordinatesTo(normals)
texturePoints[j].copyCoordinatesTo(texCoords)
}
for (j in 1..face.size - 2) {
triangles.add(copiedFace[0])
triangles.add(copiedFace[j])
triangles.add(copiedFace[j + 1])
}
}
glFrontFace(GL_CW)
glVertexPointer(4, GL_FLOAT, 0, vertices.toFloatArray().toCValues().ptr)
glTexCoordPointer(2, GL_FLOAT, 0, texCoords.toFloatArray().toCValues().ptr)
glNormalPointer(GL_FLOAT, 0, normals.toFloatArray().toCValues().ptr)
glDrawElements(GL_TRIANGLES, triangles.size, GL_UNSIGNED_BYTE, triangles.toByteArray().toCValues().ptr)
glPopMatrix()
}
private class Vector2(val x: Float, val y: Float) {
val length by lazy { sqrtf(x * x + y * y) }
fun normalized(): Vector2 {
val len = length
return Vector2(x / len, y / len)
}
fun copyCoordinatesTo(arr: MutableList<Float>) {
arr.add(x)
arr.add(y)
}
operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y)
operator fun plus(other: Vector2) = Vector2(x + other.x, y + other.y)
operator fun times(other: Float) = Vector2(x * other, y * other)
operator fun div(other: Float) = Vector2(x / other, y / other)
companion object {
val Zero = Vector2(0.0f, 0.0f)
}
}
private class Vector3(val x: Float, val y: Float, val z: Float) {
val length by lazy { sqrtf(x * x + y * y + z * z) }
fun crossProduct(other: Vector3): Vector3 =
Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x)
fun normalized(): Vector3 {
val len = length
return Vector3(x / len, y / len, z / len)
}
fun copyCoordinatesTo(arr: MutableList<Float>) {
arr.add(x)
arr.add(y)
arr.add(z)
}
operator fun minus(other: Vector3) = Vector3(x - other.x, y - other.y, z - other.z)
operator fun plus(other: Vector3) = Vector3(x + other.x, y + other.y, z + other.z)
}
private const val Zero = 0.0f
private const val DodeA = 0.93417235896f // (Sqrt(5) + 1) / (2 * Sqrt(3))
private const val DodeB = 0.35682208977f // (Sqrt(5) - 1) / (2 * Sqrt(3))
private const val DodeC = 0.57735026919f // 1 / Sqrt(3)
private const val IcosA = 0.52573111212f // Sqrt(5 - Sqrt(5)) / Sqrt(10)
private const val IcosB = 0.85065080835f // Sqrt(5 + Sqrt(5)) / Sqrt(10)
private enum class RegularPolyhedra(val vertices: Array<Vector3>, val faces: Array<ByteArray>) {
Dodecahedron(
arrayOf(
Vector3(-DodeA, Zero, DodeB), Vector3(-DodeA, Zero, -DodeB), Vector3(DodeA, Zero, -DodeB),
Vector3(DodeA, Zero, DodeB), Vector3(DodeB, -DodeA, Zero), Vector3(-DodeB, -DodeA, Zero),
Vector3(-DodeB, DodeA, Zero), Vector3(DodeB, DodeA, Zero), Vector3(Zero, DodeB, -DodeA),
Vector3(Zero, -DodeB, -DodeA), Vector3(Zero, -DodeB, DodeA), Vector3(Zero, DodeB, DodeA),
Vector3(-DodeC, -DodeC, DodeC), Vector3(-DodeC, -DodeC, -DodeC), Vector3(DodeC, -DodeC, -DodeC),
Vector3(DodeC, -DodeC, DodeC), Vector3(-DodeC, DodeC, DodeC), Vector3(-DodeC, DodeC, -DodeC),
Vector3(DodeC, DodeC, -DodeC), Vector3(DodeC, DodeC, DodeC)
),
arrayOf(
byteArrayOf(0, 12, 10, 11, 16), byteArrayOf(1, 17, 8, 9, 13), byteArrayOf(2, 14, 9, 8, 18),
byteArrayOf(3, 19, 11, 10, 15), byteArrayOf(4, 14, 2, 3, 15), byteArrayOf(5, 12, 0, 1, 13),
byteArrayOf(6, 17, 1, 0, 16), byteArrayOf(7, 19, 3, 2, 18), byteArrayOf(8, 17, 6, 7, 18),
byteArrayOf(9, 14, 4, 5, 13), byteArrayOf(10, 12, 5, 4, 15), byteArrayOf(11, 19, 7, 6, 16)
)),
Icosahedron(
arrayOf(
Vector3(-IcosA, Zero, IcosB), Vector3(IcosA, Zero, IcosB), Vector3(-IcosA, Zero, -IcosB),
Vector3(IcosA, Zero, -IcosB), Vector3(Zero, IcosB, IcosA), Vector3(Zero, IcosB, -IcosA),
Vector3(Zero, -IcosB, IcosA), Vector3(Zero, -IcosB, -IcosA), Vector3(IcosB, IcosA, Zero),
Vector3(-IcosB, IcosA, Zero), Vector3(IcosB, -IcosA, Zero), Vector3(-IcosB, -IcosA, Zero)
),
arrayOf(
byteArrayOf(1, 4, 0), byteArrayOf(4, 9, 0), byteArrayOf(4, 5, 9), byteArrayOf(8, 5, 4),
byteArrayOf(1, 8, 4), byteArrayOf(1, 10, 8), byteArrayOf(10, 3, 8), byteArrayOf(8, 3, 5),
byteArrayOf(3, 2, 5), byteArrayOf(3, 7, 2), byteArrayOf(3, 10, 7), byteArrayOf(10, 6, 7),
byteArrayOf(6, 11, 7), byteArrayOf(6, 0, 11), byteArrayOf(6, 1, 0), byteArrayOf(10, 1, 6),
byteArrayOf(11, 0, 9), byteArrayOf(2, 11, 9), byteArrayOf(5, 2, 9), byteArrayOf(11, 2, 7)
)
);
val verticesPerFace get() = faces[0].size
}
-234
View File
@@ -1,234 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
import kotlinx.cinterop.FloatVar
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.cValuesOf
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.set
import kotlinx.cinterop.toCValues
import platform.gles.GL_COLOR_BUFFER_BIT
import platform.gles.GL_CULL_FACE
import platform.gles.GL_CW
import platform.gles.GL_DEPTH_BUFFER_BIT
import platform.gles.GL_DEPTH_TEST
import platform.gles.GL_DIFFUSE
import platform.gles.GL_DITHER
import platform.gles.GL_FASTEST
import platform.gles.GL_FLOAT
import platform.gles.GL_FRONT_AND_BACK
import platform.gles.GL_LIGHT0
import platform.gles.GL_LIGHTING
import platform.gles.GL_MODELVIEW
import platform.gles.GL_NORMAL_ARRAY
import platform.gles.GL_PERSPECTIVE_CORRECTION_HINT
import platform.gles.GL_POSITION
import platform.gles.GL_PROJECTION
import platform.gles.GL_SHININESS
import platform.gles.GL_SMOOTH
import platform.gles.GL_SPECULAR
import platform.gles.GL_TEXTURE_2D
import platform.gles.GL_TEXTURE_COORD_ARRAY
import platform.gles.GL_TRIANGLES
import platform.gles.GL_UNSIGNED_BYTE
import platform.gles.GL_VERTEX_ARRAY
import platform.gles.glClear
import platform.gles.glClearColor
import platform.gles.glDisable
import platform.gles.glDrawElements
import platform.gles.glEnable
import platform.gles.glEnableClientState
import platform.gles.glFrontFace
import platform.gles.glFrustumf
import platform.gles.glHint
import platform.gles.glLightfv
import platform.gles.glLoadIdentity
import platform.gles.glMaterialf
import platform.gles.glMaterialfv
import platform.gles.glMatrixMode
import platform.gles.glMultMatrixf
import platform.gles.glNormalPointer
import platform.gles.glPopMatrix
import platform.gles.glPushMatrix
import platform.gles.glShadeModel
import platform.gles.glTexCoordPointer
import platform.gles.glTranslatef
import platform.gles.glVertexPointer
import platform.gles.glViewport
import platform.posix.sqrtf
private const val WIDTH = 600
private const val HEIGHT = 800
private const val SCALE = 1.25f
fun main() = memScoped {
glDisable(GL_DITHER)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)
glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
glEnable(GL_CULL_FACE)
glShadeModel(GL_SMOOTH)
glEnable(GL_DEPTH_TEST)
glViewport(0, 0, WIDTH, HEIGHT)
val ratio = WIDTH.toFloat() / HEIGHT
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0.0f, 0.0f, -2.0f)
glLightfv(GL_LIGHT0, GL_POSITION, cValuesOf(1.25f, 1.25f, -2.0f, 0.0f))
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_TEXTURE_2D)
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, cValuesOf(0.0f, 1.0f, 1.0f, 1.0f))
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, cValuesOf(0.3f, 0.3f, 0.3f, 1.0f))
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0f)
glPushMatrix()
glMatrixMode(GL_MODELVIEW)
val matrix = allocArray<FloatVar>(16)
for (i in 0..3)
for (j in 0..3)
matrix[i * 4 + j] = if (i == j) 1.0f else 0.0f
glMultMatrixf(matrix)
glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).toUInt())
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
val polygon = RegularPolyhedra.Dodecahedron
val vertices = mutableListOf<Float>()
val texCoords = mutableListOf<Float>()
val triangles = mutableListOf<Byte>()
val normals = mutableListOf<Float>()
val texturePoints = arrayOf(Vector2(0.0f, 0.2f), Vector2(0.0f, 0.8f), Vector2(0.6f, 1.0f), Vector2(1.0f, 0.5f), Vector2(0.8f, 0.0f))
for (face in polygon.faces) {
val u = polygon.vertices[face[2].toInt()] - polygon.vertices[face[1].toInt()]
val v = polygon.vertices[face[0].toInt()] - polygon.vertices[face[1].toInt()]
val normal = u.crossProduct(v).normalized()
val copiedFace = ByteArray(face.size)
for (j in face.indices) {
copiedFace[j] = (vertices.size / 4).toByte()
polygon.vertices[face[j].toInt()].copyCoordinatesTo(vertices)
vertices.add(SCALE)
normal.copyCoordinatesTo(normals)
texturePoints[j].copyCoordinatesTo(texCoords)
}
for (j in 1..face.size - 2) {
triangles.add(copiedFace[0])
triangles.add(copiedFace[j])
triangles.add(copiedFace[j + 1])
}
}
glFrontFace(GL_CW)
glVertexPointer(4, GL_FLOAT, 0, vertices.toFloatArray().toCValues().ptr)
glTexCoordPointer(2, GL_FLOAT, 0, texCoords.toFloatArray().toCValues().ptr)
glNormalPointer(GL_FLOAT, 0, normals.toFloatArray().toCValues().ptr)
glDrawElements(GL_TRIANGLES, triangles.size, GL_UNSIGNED_BYTE, triangles.toByteArray().toCValues().ptr)
glPopMatrix()
}
private class Vector2(val x: Float, val y: Float) {
val length by lazy { sqrtf(x * x + y * y) }
fun normalized(): Vector2 {
val len = length
return Vector2(x / len, y / len)
}
fun copyCoordinatesTo(arr: MutableList<Float>) {
arr.add(x)
arr.add(y)
}
operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y)
operator fun plus(other: Vector2) = Vector2(x + other.x, y + other.y)
operator fun times(other: Float) = Vector2(x * other, y * other)
operator fun div(other: Float) = Vector2(x / other, y / other)
companion object {
val Zero = Vector2(0.0f, 0.0f)
}
}
private class Vector3(val x: Float, val y: Float, val z: Float) {
val length by lazy { sqrtf(x * x + y * y + z * z) }
fun crossProduct(other: Vector3): Vector3 =
Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x)
fun normalized(): Vector3 {
val len = length
return Vector3(x / len, y / len, z / len)
}
fun copyCoordinatesTo(arr: MutableList<Float>) {
arr.add(x)
arr.add(y)
arr.add(z)
}
operator fun minus(other: Vector3) = Vector3(x - other.x, y - other.y, z - other.z)
operator fun plus(other: Vector3) = Vector3(x + other.x, y + other.y, z + other.z)
}
private const val Zero = 0.0f
private const val DodeA = 0.93417235896f // (Sqrt(5) + 1) / (2 * Sqrt(3))
private const val DodeB = 0.35682208977f // (Sqrt(5) - 1) / (2 * Sqrt(3))
private const val DodeC = 0.57735026919f // 1 / Sqrt(3)
private const val IcosA = 0.52573111212f // Sqrt(5 - Sqrt(5)) / Sqrt(10)
private const val IcosB = 0.85065080835f // Sqrt(5 + Sqrt(5)) / Sqrt(10)
private enum class RegularPolyhedra(val vertices: Array<Vector3>, val faces: Array<ByteArray>) {
Dodecahedron(
arrayOf(
Vector3(-DodeA, Zero, DodeB), Vector3(-DodeA, Zero, -DodeB), Vector3(DodeA, Zero, -DodeB),
Vector3(DodeA, Zero, DodeB), Vector3(DodeB, -DodeA, Zero), Vector3(-DodeB, -DodeA, Zero),
Vector3(-DodeB, DodeA, Zero), Vector3(DodeB, DodeA, Zero), Vector3(Zero, DodeB, -DodeA),
Vector3(Zero, -DodeB, -DodeA), Vector3(Zero, -DodeB, DodeA), Vector3(Zero, DodeB, DodeA),
Vector3(-DodeC, -DodeC, DodeC), Vector3(-DodeC, -DodeC, -DodeC), Vector3(DodeC, -DodeC, -DodeC),
Vector3(DodeC, -DodeC, DodeC), Vector3(-DodeC, DodeC, DodeC), Vector3(-DodeC, DodeC, -DodeC),
Vector3(DodeC, DodeC, -DodeC), Vector3(DodeC, DodeC, DodeC)
),
arrayOf(
byteArrayOf(0, 12, 10, 11, 16), byteArrayOf(1, 17, 8, 9, 13), byteArrayOf(2, 14, 9, 8, 18),
byteArrayOf(3, 19, 11, 10, 15), byteArrayOf(4, 14, 2, 3, 15), byteArrayOf(5, 12, 0, 1, 13),
byteArrayOf(6, 17, 1, 0, 16), byteArrayOf(7, 19, 3, 2, 18), byteArrayOf(8, 17, 6, 7, 18),
byteArrayOf(9, 14, 4, 5, 13), byteArrayOf(10, 12, 5, 4, 15), byteArrayOf(11, 19, 7, 6, 16)
)),
Icosahedron(
arrayOf(
Vector3(-IcosA, Zero, IcosB), Vector3(IcosA, Zero, IcosB), Vector3(-IcosA, Zero, -IcosB),
Vector3(IcosA, Zero, -IcosB), Vector3(Zero, IcosB, IcosA), Vector3(Zero, IcosB, -IcosA),
Vector3(Zero, -IcosB, IcosA), Vector3(Zero, -IcosB, -IcosA), Vector3(IcosB, IcosA, Zero),
Vector3(-IcosB, IcosA, Zero), Vector3(IcosB, -IcosA, Zero), Vector3(-IcosB, -IcosA, Zero)
),
arrayOf(
byteArrayOf(1, 4, 0), byteArrayOf(4, 9, 0), byteArrayOf(4, 5, 9), byteArrayOf(8, 5, 4),
byteArrayOf(1, 8, 4), byteArrayOf(1, 10, 8), byteArrayOf(10, 3, 8), byteArrayOf(8, 3, 5),
byteArrayOf(3, 2, 5), byteArrayOf(3, 7, 2), byteArrayOf(3, 10, 7), byteArrayOf(10, 6, 7),
byteArrayOf(6, 11, 7), byteArrayOf(6, 0, 11), byteArrayOf(6, 1, 0), byteArrayOf(10, 1, 6),
byteArrayOf(11, 0, 9), byteArrayOf(2, 11, 9), byteArrayOf(5, 2, 9), byteArrayOf(11, 2, 7)
)
);
val verticesPerFace get() = faces[0].size
}
@@ -3,6 +3,9 @@
* that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch")
package perfTestPackage1 // this package is mandatory
import kotlinx.cinterop.ExportObjCClass
import kotlinx.cinterop.ObjCAction
import kotlinx.cinterop.ObjCOutlet
@@ -1,140 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
import kotlinx.cinterop.ExportObjCClass
import kotlinx.cinterop.ObjCAction
import kotlinx.cinterop.ObjCOutlet
import kotlinx.cinterop.autoreleasepool
import kotlinx.cinterop.cstr
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.toCValues
import kotlinx.cinterop.useContents
import platform.CoreGraphics.CGPointMake
import platform.CoreGraphics.CGRectMake
import platform.Foundation.NSCoder
import platform.Foundation.NSSelectorFromString
import platform.Foundation.NSStringFromClass
import platform.UIKit.NSTextAlignmentCenter
import platform.UIKit.UIApplication
import platform.UIKit.UIApplicationDelegateProtocol
import platform.UIKit.UIApplicationDelegateProtocolMeta
import platform.UIKit.UIApplicationMain
import platform.UIKit.UIButton
import platform.UIKit.UIColor
import platform.UIKit.UIControlEventTouchUpInside
import platform.UIKit.UIControlStateNormal
import platform.UIKit.UIFont
import platform.UIKit.UILabel
import platform.UIKit.UIResponder
import platform.UIKit.UIResponderMeta
import platform.UIKit.UIScreen
import platform.UIKit.UIView
import platform.UIKit.UIViewController
import platform.UIKit.UIWindow
import platform.UIKit.addSubview
import platform.UIKit.backgroundColor
import platform.UIKit.font
import platform.UIKit.heightAnchor
import platform.UIKit.leadingAnchor
import platform.UIKit.setFrame
import platform.UIKit.topAnchor
import platform.UIKit.translatesAutoresizingMaskIntoConstraints
import platform.UIKit.widthAnchor
fun main(args: Array<String>) {
memScoped {
val argc = args.size + 1
val argv = (arrayOf("konan") + args).map { it.cstr.ptr }.toCValues()
autoreleasepool {
UIApplicationMain(argc, argv, null, NSStringFromClass(AppDelegate))
}
}
}
private class AppDelegate : UIResponder, UIApplicationDelegateProtocol {
companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta {}
@OverrideInit
constructor() : super()
private var _window: UIWindow? = null
override fun window() = _window
override fun setWindow(window: UIWindow?) {
_window = window
}
override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean {
window = UIWindow(frame = UIScreen.mainScreen.bounds)
window!!.rootViewController = ViewController()
window!!.makeKeyAndVisible()
return true
}
}
@ExportObjCClass
private class ViewController : UIViewController {
@OverrideInit
constructor() : super(nibName = null, bundle = null)
@OverrideInit
constructor(coder: NSCoder) : super(coder)
@ObjCOutlet
lateinit var label: UILabel
@ObjCOutlet
lateinit var button: UIButton
var pressed = 0
@ObjCAction
fun buttonPressed() {
label.text = "Hello #${pressed++} from Konan!"
println("Button pressed")
}
override fun viewDidLoad() {
super.viewDidLoad()
val (width, height) = UIScreen.mainScreen.bounds.useContents {
this.size.width to this.size.height
}
val header = UIView().apply {
backgroundColor = UIColor.lightGrayColor
view.addSubview(this)
translatesAutoresizingMaskIntoConstraints = false
leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
widthAnchor.constraintEqualToAnchor(view.widthAnchor).active = true
heightAnchor.constraintEqualToAnchor(view.heightAnchor).active = true
}
label = UILabel().apply {
setFrame(CGRectMake(x = 10.0, y = 10.0, width = width - 100.0, height = 40.0))
center = CGPointMake(x = width / 2, y = 40.0 )
textAlignment = NSTextAlignmentCenter
text = "Press OK"
header.addSubview(this)
}
button = UIButton().apply {
setFrame(CGRectMake(x = 10.0, y = height - 100.0, width = width - 100.0, height = 40.0))
center = CGPointMake(x = width / 2, y = height / 2)
backgroundColor = UIColor.blueColor
setTitle("OK", forState = UIControlStateNormal)
font = UIFont.fontWithName(fontName = font.fontName, size = 28.0)!!
layer.borderWidth = 1.0
layer.borderColor = UIColor.colorWithRed(0x47 / 255.0, 0x43 / 255.0, 0x70 / 255.0, 1.0).CGColor
layer.masksToBounds = true
addTarget(target = this@ViewController, action = NSSelectorFromString("buttonPressed"),
forControlEvents = UIControlEventTouchUpInside)
header.addSubview(this)
}
}
}
@@ -1,140 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
import kotlinx.cinterop.ExportObjCClass
import kotlinx.cinterop.ObjCAction
import kotlinx.cinterop.ObjCOutlet
import kotlinx.cinterop.autoreleasepool
import kotlinx.cinterop.cstr
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.toCValues
import kotlinx.cinterop.useContents
import platform.CoreGraphics.CGPointMake
import platform.CoreGraphics.CGRectMake
import platform.Foundation.NSCoder
import platform.Foundation.NSSelectorFromString
import platform.Foundation.NSStringFromClass
import platform.UIKit.NSTextAlignmentCenter
import platform.UIKit.UIApplication
import platform.UIKit.UIApplicationDelegateProtocol
import platform.UIKit.UIApplicationDelegateProtocolMeta
import platform.UIKit.UIApplicationMain
import platform.UIKit.UIButton
import platform.UIKit.UIColor
import platform.UIKit.UIControlEventTouchUpInside
import platform.UIKit.UIControlStateNormal
import platform.UIKit.UIFont
import platform.UIKit.UILabel
import platform.UIKit.UIResponder
import platform.UIKit.UIResponderMeta
import platform.UIKit.UIScreen
import platform.UIKit.UIView
import platform.UIKit.UIViewController
import platform.UIKit.UIWindow
import platform.UIKit.addSubview
import platform.UIKit.backgroundColor
import platform.UIKit.font
import platform.UIKit.heightAnchor
import platform.UIKit.leadingAnchor
import platform.UIKit.setFrame
import platform.UIKit.topAnchor
import platform.UIKit.translatesAutoresizingMaskIntoConstraints
import platform.UIKit.widthAnchor
fun main(args: Array<String>) {
memScoped {
val argc = args.size + 1
val argv = (arrayOf("konan") + args).map { it.cstr.ptr }.toCValues()
autoreleasepool {
UIApplicationMain(argc, argv, null, NSStringFromClass(AppDelegate))
}
}
}
private class AppDelegate : UIResponder, UIApplicationDelegateProtocol {
companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta {}
@OverrideInit
constructor() : super()
private var _window: UIWindow? = null
override fun window() = _window
override fun setWindow(window: UIWindow?) {
_window = window
}
override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean {
window = UIWindow(frame = UIScreen.mainScreen.bounds)
window!!.rootViewController = ViewController()
window!!.makeKeyAndVisible()
return true
}
}
@ExportObjCClass
private class ViewController : UIViewController {
@OverrideInit
constructor() : super(nibName = null, bundle = null)
@OverrideInit
constructor(coder: NSCoder) : super(coder)
@ObjCOutlet
lateinit var label: UILabel
@ObjCOutlet
lateinit var button: UIButton
var pressed = 0
@ObjCAction
fun buttonPressed() {
label.text = "Hello #${pressed++} from Konan!"
println("Button pressed")
}
override fun viewDidLoad() {
super.viewDidLoad()
val (width, height) = UIScreen.mainScreen.bounds.useContents {
this.size.width to this.size.height
}
val header = UIView().apply {
backgroundColor = UIColor.lightGrayColor
view.addSubview(this)
translatesAutoresizingMaskIntoConstraints = false
leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
widthAnchor.constraintEqualToAnchor(view.widthAnchor).active = true
heightAnchor.constraintEqualToAnchor(view.heightAnchor).active = true
}
label = UILabel().apply {
setFrame(CGRectMake(x = 10.0, y = 10.0, width = width - 100.0, height = 40.0))
center = CGPointMake(x = width / 2, y = 40.0 )
textAlignment = NSTextAlignmentCenter
text = "Press OK"
header.addSubview(this)
}
button = UIButton().apply {
setFrame(CGRectMake(x = 10.0, y = height - 100.0, width = width - 100.0, height = 40.0))
center = CGPointMake(x = width / 2, y = height / 2)
backgroundColor = UIColor.blueColor
setTitle("OK", forState = UIControlStateNormal)
font = UIFont.fontWithName(fontName = font.fontName, size = 28.0)!!
layer.borderWidth = 1.0
layer.borderColor = UIColor.colorWithRed(0x47 / 255.0, 0x43 / 255.0, 0x70 / 255.0, 1.0).CGColor
layer.masksToBounds = true
addTarget(target = this@ViewController, action = NSSelectorFromString("buttonPressed"),
forControlEvents = UIControlEventTouchUpInside)
header.addSubview(this)
}
}
}