Skip to content

Commit

Permalink
optimize RenderInstance by replacing it with struct
Browse files Browse the repository at this point in the history
  • Loading branch information
SpaiR committed Jun 12, 2019
1 parent bf126ec commit f53172d
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 107 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 1,5 @@
[*]
end_of_line=lf
insert_final_newline=true
indent_style=space
indent_size=4
33 changes: 26 additions & 7 deletions src/main/kotlin/io/github/spair/strongdmm/gui/map/MapPipeline.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 6,7 @@ import io.github.spair.strongdmm.gui.map.select.SelectOperation
import io.github.spair.strongdmm.logic.dmi.DmiProvider
import io.github.spair.strongdmm.logic.map.Dmm
import io.github.spair.strongdmm.logic.map.OUT_OF_BOUNDS
import io.github.spair.strongdmm.logic.render.RenderInstanceStruct
import io.github.spair.strongdmm.logic.render.VisualComposer
import org.lwjgl.opengl.Display
import org.lwjgl.opengl.GL11.*
Expand Down Expand Up @@ -163,19 164,37 @@ class MapPipeline(private val canvas: Canvas) {

renderInstances.values.forEach { plane ->
plane.values.forEach { layer ->
layer.forEach { ri ->
glColor4f(ri.color.red, ri.color.green, ri.color.blue, ri.color.alpha)
layer.forEach { riAddress ->
val colorRed = RenderInstanceStruct.getColorRed(riAddress)
val colorGreen = RenderInstanceStruct.getColorGreen(riAddress)
val colorBlue = RenderInstanceStruct.getColorBlue(riAddress)
val colorAlpha = RenderInstanceStruct.getColorAlpha(riAddress)

if (ri.textureId != bindedTexture) {
glBindTexture(GL_TEXTURE_2D, ri.textureId)
bindedTexture = ri.textureId
glColor4f(colorRed, colorGreen, colorBlue, colorAlpha)

val textureId = RenderInstanceStruct.getTextureId(riAddress)

if (textureId != bindedTexture) {
glBindTexture(GL_TEXTURE_2D, textureId)
bindedTexture = textureId
}

val locX = RenderInstanceStruct.getLocX(riAddress)
val locY = RenderInstanceStruct.getLocY(riAddress)

glPushMatrix()
glTranslatef(ri.locX, ri.locY, 0f)
glTranslatef(locX, locY, 0f)

val width = RenderInstanceStruct.getWidth(riAddress)
val height = RenderInstanceStruct.getHeight(riAddress)

val u1 = RenderInstanceStruct.getU1(riAddress)
val v1 = RenderInstanceStruct.getV1(riAddress)
val u2 = RenderInstanceStruct.getU2(riAddress)
val v2 = RenderInstanceStruct.getV2(riAddress)

glBegin(GL_QUADS)
with(ri) {
run {
glTexCoord2f(u2, v1)
glVertex2i(width, height)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 4,39 @@ import io.github.spair.strongdmm.gui.objtree.ObjectTreeView
import io.github.spair.strongdmm.logic.dmi.DmiProvider
import io.github.spair.strongdmm.logic.map.TileItem
import io.github.spair.strongdmm.logic.map.TileItemProvider
import io.github.spair.strongdmm.logic.render.RenderInstance
import io.github.spair.strongdmm.logic.render.RenderInstanceStruct
import io.github.spair.strongdmm.logic.render.RenderInstances

fun MapPipeline.findAndSelectItemUnderMouse(renderInstances: RenderInstances) {
val instances = mutableListOf<RenderInstance>()
val addresses = mutableListOf<Long>()

renderInstances.values.forEach { plane ->
plane.values.forEach { layer ->
layer.forEach { ri ->
if (xMouse in ri.locX..(ri.locX ri.width) && yMouse in ri.locY..(ri.locY ri.width)) {
instances.add(ri)
layer.forEach { riAddress ->
val locX = RenderInstanceStruct.getLocX(riAddress)
val locY = RenderInstanceStruct.getLocY(riAddress)
val width = RenderInstanceStruct.getWidth(riAddress)
val height = RenderInstanceStruct.getHeight(riAddress)

if (xMouse in locX..(locX width) && yMouse in locY..(locY height)) {
addresses.add(riAddress)
}
}
}
}

var selectedItem: TileItem? = null

instances.forEach { ri ->
val pixelX = (xMouse - ri.locX).toInt()
val pixelY = (ri.width - (yMouse - ri.locY)).toInt()
addresses.forEach { riAddress ->
val locX = RenderInstanceStruct.getLocX(riAddress)
val locY = RenderInstanceStruct.getLocY(riAddress)
val width = RenderInstanceStruct.getWidth(riAddress)
val tileItemID = RenderInstanceStruct.getTileItemId(riAddress)

val item = TileItemProvider.getByID(ri.tileItemID)
val pixelX = (xMouse - locX).toInt()
val pixelY = (width - (yMouse - locY)).toInt()

val item = TileItemProvider.getByID(tileItemID)
val isOpaque = DmiProvider.getSpriteFromDmi(item.icon, item.iconState, item.dir)?.isOpaquePixel(pixelX, pixelY)
?: true // When there is no sprite for item we are using placeholder which is always opaque

Expand Down
31 changes: 23 additions & 8 deletions src/main/kotlin/io/github/spair/strongdmm/logic/dme/models.kt
Original file line number Diff line number Diff line change
@@ -1,5 1,8 @@
package io.github.spair.strongdmm.logic.dme

const val NON_EXISTENT_FLOAT: Float = -99999999999999999999999999999999999999f
const val NON_EXISTENT_INT: Int = -999999999

class Dme(private val dmeItems: Map<String, DmeItem?>) {
fun getItem(type: String) = dmeItems[type]
}
Expand All @@ -9,13 12,13 @@ class DmeItem(
val type: String,
val vars: Map<String, String>,
val children: List<String>
) {

) {
private val lookedVars = mutableMapOf<String, String?>()

val parent get() = parentType?.let { environment.getItem(it) }
val parent
get() = parentType?.let { environment.getItem(it) }

val parentType by lazy {
private val parentType by lazy {
when (type) {
TYPE_DATUM -> null
TYPE_ATOM -> TYPE_DATUM
Expand All @@ -25,8 28,6 @@ class DmeItem(
}
}

fun isType(type: String) = isType(this.type, type)

fun getVar(name: String): String? {
if (vars.containsKey(name)) {
return vars[name]
Expand All @@ -41,8 42,22 @@ class DmeItem(
}

fun getVarText(name: String) = getVar(name)?.takeIf { it.isNotEmpty() }?.run { substring(1, length - 1) }
fun getVarFloat(name: String) = getVar(name)?.toFloatOrNull()
fun getVarInt(name: String) = getVar(name)?.toIntOrNull()

fun getVarFloat(name: String): Float {
return try {
getVar(name)?.toFloat() ?: NON_EXISTENT_FLOAT
} catch (e: NumberFormatException) {
NON_EXISTENT_FLOAT
}
}

fun getVarInt(name: String): Int {
return try {
getVar(name)?.toInt() ?: NON_EXISTENT_INT
} catch (e: NumberFormatException) {
NON_EXISTENT_INT
}
}

override fun toString(): String {
return "DmeItem(type='$type', vars=$vars, children=$children)"
Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/io/github/spair/strongdmm/logic/map/Dmm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 2,7 @@ package io.github.spair.strongdmm.logic.map

import io.github.spair.dmm.io.*
import io.github.spair.strongdmm.logic.dme.Dme
import io.github.spair.strongdmm.logic.dme.NON_EXISTENT_INT
import io.github.spair.strongdmm.logic.dme.TYPE_WORLD
import io.github.spair.strongdmm.logic.dme.VAR_ICON_SIZE
import io.github.spair.strongdmm.logic.history.DeleteTileItemAction
Expand All @@ -16,7 17,7 @@ class Dmm(mapFile: File, val initialDmmData: DmmData, dme: Dme) {

val maxX: Int = initialDmmData.maxX
val maxY: Int = initialDmmData.maxY
val iconSize: Int = dme.getItem(TYPE_WORLD)!!.getVarInt(VAR_ICON_SIZE) ?: 32
val iconSize: Int = dme.getItem(TYPE_WORLD)!!.getVarInt(VAR_ICON_SIZE).let { if (it == NON_EXISTENT_INT) 32 else it }

private val tiles: Array<Array<Tile?>>

Expand Down Expand Up @@ -90,4 91,4 @@ class Dmm(mapFile: File, val initialDmmData: DmmData, dme: Dme) {
override fun hashCode(): Int {
return mapPath.hashCode()
}
}
}
7 changes: 6 additions & 1 deletion src/main/kotlin/io/github/spair/strongdmm/logic/map/Tile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 81,12 @@ class Tile(val x: Int, val y: Int, private var tileItemsIDs: IntArray) {
val tmpArr = IntArray(tileItemsIDs.size - 1)
var counter = 0

tileItemsIDs.forEach { tileItemID ->
for (tileItemID in tileItemsIDs) {
// Sometimes it's happens
if (counter != tmpArr.size) {
break
}

if (tileItemID != tileItem.id) {
tmpArr[counter ] = tileItemID
}
Expand Down
39 changes: 28 additions & 11 deletions src/main/kotlin/io/github/spair/strongdmm/logic/map/TileItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 13,35 @@ class TileItem(val id: Int, val type: String, customVars: Map<String, String>? =
// Vars extensively used during rendering
val icon: String = getVarText(VAR_ICON) ?: ""
val iconState: String = getVarText(VAR_ICON_STATE) ?: ""
val alpha: Int = getVarInt(VAR_ALPHA) ?: 255
val plane: Float = getVarFloat(VAR_PLANE) ?: 0f
val layer: Float = getVarFloat(VAR_LAYER) ?: 0f
val pixelX: Int = getVarInt(VAR_PIXEL_X) ?: 0
val pixelY: Int = getVarInt(VAR_PIXEL_Y) ?: 0
val dir: Int = getVarInt(VAR_DIR) ?: SOUTH
val alpha: Int = getVarInt(VAR_ALPHA).let { if (it == NON_EXISTENT_INT) 255 else it }
val plane: Float = getVarFloat(VAR_PLANE).let { if (it == NON_EXISTENT_FLOAT) 0f else it }
val layer: Float = getVarFloat(VAR_LAYER).let { if (it == NON_EXISTENT_FLOAT) 0f else it }
val pixelX: Int = getVarInt(VAR_PIXEL_X).let { if (it == NON_EXISTENT_INT) 0 else it }
val pixelY: Int = getVarInt(VAR_PIXEL_Y).let { if (it == NON_EXISTENT_INT) 0 else it }
val dir: Int = getVarInt(VAR_DIR).let { if (it == NON_EXISTENT_INT) SOUTH else it }
val color: String = getVarText(VAR_COLOR) ?: ""

fun isType(otherType: String): Boolean = isType(type, otherType)

fun getVar(name: String): String? = customVars?.get(name) ?: dmeItem.getVar(name)
fun getVarText(name: String): String? = customVars?.get(name)?.takeIf { it.isNotEmpty() }?.run { substring(1, length - 1) } ?: dmeItem.getVarText(name)
fun getVarInt(name: String): Int? = customVars?.get(name)?.toIntOrNull() ?: dmeItem.getVarInt(name)
fun getVarFloat(name: String): Float? = customVars?.get(name)?.toFloatOrNull() ?: dmeItem.getVarFloat(name)
}
fun getVarText(name: String): String? {
return customVars?.get(name)?.takeIf { it.isNotEmpty() }?.run {
substring(1, length - 1)
} ?: dmeItem.getVarText(name)
}

private fun getVarInt(name: String): Int {
return try {
customVars?.get(name)?.toInt() ?: dmeItem.getVarInt(name)
} catch (e: NumberFormatException) {
NON_EXISTENT_INT
}
}

private fun getVarFloat(name: String): Float {
return try {
customVars?.get(name)?.toFloat() ?: dmeItem.getVarFloat(name)
} catch (e: NumberFormatException) {
NON_EXISTENT_FLOAT
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 28,7 @@ object ColorExtractor {
"aqua" to "#00ffff", "cyan" to "#00ffff"
)

fun extractColor(tileItem: TileItem): Color {
fun extractAndSetColor(riAddress: Long, tileItem: TileItem) {
var colorValue = tileItem.color

if (colorValue.startsWith(RGB_PREFIX)) {
Expand All @@ -49,13 49,14 @@ object ColorExtractor {
val alpha = tileItem.alpha / 255f

if (alpha == 1f && awtColor == null) {
return DefaultColor
RenderInstanceStruct.setColor(riAddress)
return
}

return if (awtColor != null) {
Color(awtColor.red / 255f, awtColor.green / 255f, awtColor.blue / 255f, alpha)
if (awtColor != null) {
RenderInstanceStruct.setColor(riAddress, awtColor.red / 255f, awtColor.green / 255f, awtColor.blue / 255f, alpha)
} else {
Color(alpha = alpha)
RenderInstanceStruct.setColor(riAddress, colorAlpha = alpha)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 1,23 @@
package io.github.spair.strongdmm.logic.render

import io.github.spair.strongdmm.logic.dme.TYPE_AREA
import io.github.spair.strongdmm.logic.dme.TYPE_MOB
import io.github.spair.strongdmm.logic.dme.TYPE_OBJ
import io.github.spair.strongdmm.logic.dme.TYPE_TURF
import io.github.spair.strongdmm.logic.dme.*
import io.github.spair.strongdmm.logic.map.TileItemProvider

object RenderComparator : Comparator<RenderInstance> {
object RenderComparator : Comparator<Long> {

private val RENDER_PRIORITY = arrayOf(TYPE_TURF, TYPE_OBJ, TYPE_MOB, TYPE_AREA)

override fun compare(ri1: RenderInstance, ri2: RenderInstance): Int {
val tileItem1 = TileItemProvider.getByID(ri1.tileItemID)
val tileItem2 = TileItemProvider.getByID(ri2.tileItemID)
override fun compare(riAddress1: Long, riAddress2: Long): Int {
val tileItem1 = TileItemProvider.getByID(RenderInstanceStruct.getTileItemId(riAddress1))
val tileItem2 = TileItemProvider.getByID(RenderInstanceStruct.getTileItemId(riAddress2))

val type1 = tileItem1.type
val type2 = tileItem2.type

if (isType(type1, type2)) {
return 0
}

for (type in RENDER_PRIORITY) {
if (type1.startsWith(type) && !type2.startsWith(type)) {
return -1
Expand All @@ -25,16 26,6 @@ object RenderComparator : Comparator<RenderInstance> {
}
}

val plane1 = tileItem1.plane
val plane2 = tileItem2.plane

if (!plane1.equals(plane2)) {
return plane1.compareTo(plane2)
}

val layer1 = tileItem1.layer
val layer2 = tileItem2.layer

return layer1.compareTo(layer2)
return 0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 18,31 @@ object RenderInstanceProvider : EnvCleanable {
locked = false
}

fun create(x: Float, y: Float, tileItem: TileItem): RenderInstance {
fun create(x: Float, y: Float, tileItem: TileItem): Long {
val icon = tileItem.icon
val riAddress = RenderInstanceStruct.allocate()

if (DmiProvider.hasDmiInMemory(icon)) {
hasInProcessImage = false
return DmiProvider.getDmi(icon)?.let { dmi ->
dmi.getIconState(tileItem.iconState)?.getIconSprite(tileItem.dir)?.let { s ->
RenderInstance(
x tileItem.pixelX, y tileItem.pixelY,
dmi.glTextureId,
s.u1, s.v1, s.u2, s.v2,
s.iconWidth, s.iconHeight,
ColorExtractor.extractColor(tileItem),
tileItem.id
)
}
} ?: RenderInstance(x, y, DmiProvider.placeholderTextureId, tileItemID = tileItem.id)

val dmi = DmiProvider.getDmi(icon)
val sprite = dmi?.getIconState(tileItem.iconState)?.getIconSprite(tileItem.dir)

if (sprite != null) {
RenderInstanceStruct.setMajor(
riAddress,
x tileItem.pixelX, y tileItem.pixelY,
dmi.glTextureId,
sprite.u1, sprite.v1, sprite.u2, sprite.v2,
sprite.iconWidth, sprite.iconHeight,
tileItem.id
)

ColorExtractor.extractAndSetColor(riAddress, tileItem)
} else {
RenderInstanceStruct.setMajor(riAddress, x, y, DmiProvider.placeholderTextureId, tileItemID = tileItem.id)
RenderInstanceStruct.setColor(riAddress)
}
} else {
hasInProcessImage = true

Expand All @@ -46,7 54,10 @@ object RenderInstanceProvider : EnvCleanable {
}
}

return RenderInstance(x, y, DmiProvider.placeholderTextureId, tileItemID = tileItem.id)
RenderInstanceStruct.setMajor(riAddress, x, y, DmiProvider.placeholderTextureId, tileItemID = tileItem.id)
RenderInstanceStruct.setColor(riAddress)
}

return riAddress
}
}
Loading

0 comments on commit f53172d

Please sign in to comment.