From af619cda79d961534f76090f9bd9490797847d3d Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 8 Feb 2019 11:46:30 +0900 Subject: [PATCH] instead of frequently accessing Java from C-side, feed everything beforehand on Java-side --- .../worlddrawer/FireRecalculateEvent.c | 118 +++++------------- .../worlddrawer/LightmapRendererNew.kt | 15 ++- ...ld_terrarum_worlddrawer_LightmapRenderer.h | 4 +- 3 files changed, 45 insertions(+), 92 deletions(-) diff --git a/src/net/torvald/terrarum/worlddrawer/FireRecalculateEvent.c b/src/net/torvald/terrarum/worlddrawer/FireRecalculateEvent.c index ce5a19772..e603f397a 100644 --- a/src/net/torvald/terrarum/worlddrawer/FireRecalculateEvent.c +++ b/src/net/torvald/terrarum/worlddrawer/FireRecalculateEvent.c @@ -1,15 +1,14 @@ #include #include +#include #include "net_torvald_terrarum_worlddrawer_LightmapRenderer.h" /* compile required headers with: -"C:\Program Files\Java\jdk1.8.0_131\bin\javah.exe" -jni -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\terr -arum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.worlddrawer.LightmapRenderer +"C:\Program Files\Java\jdk1.8.0_131\bin\javah.exe" -jni -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\terrarum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.worlddrawer.LightmapRenderer get method signatures with: -"C:\Program Files\Java\jdk1.8.0_131\bin\javap.exe" -s -p -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\ter -rarum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.gameworld.GameWorld +"C:\Program Files\Java\jdk1.8.0_131\bin\javap.exe" -s -p -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\terrarum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.gameworld.GameWorld */ #define vec4 __m128 @@ -32,58 +31,14 @@ const vec4 oneVec = _mm_set1_ps(1); const vec4 zeroVec = _mm_set1_ps(0); const vec4 sqrt2Vec = _mm_set1_ps(1.41421356f); -int LIGHTMAP_WIDTH; -int for_x_start = 0; -int for_y_start = 0; -int for_x_end = 0; -int for_y_end = 0; +int LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT; +int for_x_start; +int for_y_start; +int for_x_end; +int for_y_end; -void getLightsAndShades(JNIEnv *env, jclass cls, jobject obj, int x, int y) { - // get world first - jfieldID fid = (*env)->GetFieldID(env, cls, "world", "Lnet/torvald/terrarum/gameworld/GameWorld;"); - jobject worldobj = (*env)->GetObjectField(env, obj, fid); - jclass worldcls = (*env)->GetObjectClass(env, worldobj); +void getLightsAndShades(int x, int y, jfloatArray lightmap, jintArray groundmap, jfloatArray lummap, jfloatArray shademap, jbyteArray fluidtypemap, jfloatArray fluidfillmap, jfloatArray sun) { - // get method IDs - jmethodID getTerrain_mid = (*env)->GetMethodID(env, worldcls, "getTileFromTerrain", "(II)Ljava/lang/Integer;") - jmethodID getFluid_mid = (*env)->GetMethodID(env, worldcls, "getFluid", "(II)Lnet/torvald/terrarum/gameworld/GameWorld$FluidInfo;") - jmethodID getWall_mid = (*env)->GetMethodID(env, worldcls, "getTileFromWall", "(II)Ljava/lang/Integer;") - jmethodID getSun_mid = (*env)->GetMethodID(env, worldcls, "getGlobalLight", "()Lcom/badlogic/gdx/graphics/Color;") - - // populate the vars - thisTerrain = (*env)->CallObjectMethod(env, worldobj, getTerrain_mid, x, y); - thisFluid = (*env)->CallObjectMethod(env, worldobj, getFluid_mid, x, y); - thisWall = (*env)->CallObjectMethod(env, worldobj, getWall_mid, x, y); - - // set sunlight - jobject sun_gdxcolor = (*env)->CallObjectMethod(env, worldobj, getSun_mid, x, y); - jclass gdxcolor_cls = (*env)->GetObjectClass(env, sun_gdxcolor); - jfieldID sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "r", "F"); - float sunr = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; - sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "g", "F"); - float sung = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; - sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "b", "F"); - float sunb = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; - sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "a", "F"); - float suna = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; - - // TODO check rgba argument order (RGBA or ABGR, intel doc is confusing) - sunLight = _mm_set_ps(sunr, sung, sunb, suna); - - // get fluid info - jclass fluid_cls = (*env)->GetObjectClass(env, thisFluid); - jfieldID fluidfid = (*env)->GetFieldID(env, fluid_cls, "type", "I"); - jint fluidType = GetIntField(env, thisFluid, fluidfid); - fluidfid = (*env)->GetFieldID(env, fluid_cls, "amount", "F"); - jfloat fluidFill = GetIntField(env, thisFluid, fluidfid); - - - lightLevelThis = _mm_set1_ps(0); - - if (fluidType != 0) { - fluidAmountToCol = _mm_set1_ps(fluidFill); - thisTileLuminosity = - } } @@ -117,7 +72,7 @@ vec4 calculate(int x, int y) { return lightLevelThis } -void setLightOf(JNIEnv *env, jclass cls, int x, int y, vec4 colour) { +void setLightOf(jfloatArray lightmap, int x, int y, vec4 colour) { if (y - for_y_start + overscan_open >= 0 && y - for_y_start + overscan_open < LIGHTMAP_HEIGHT && @@ -131,21 +86,17 @@ void setLightOf(JNIEnv *env, jclass cls, int x, int y, vec4 colour) { float[4] vector; _mm_store_ps(vector *, colour); - // get the array - jfieldID fid = (*env)->GetFieldID(env, cls, "lightmap", "F"); - jfloat * list = (*env)->GetFloatArrayElements(env, jfloatarray, null); - // set r/g/b/a values - list[4 * (ypos * LIGHTMAP_WIDTH + xpos)] = vector[0]; - list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1] = vector[1]; - list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2] = vector[2]; - list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3] = vector[3]; + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos)] = vector[0]; + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1] = vector[1]; + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2] = vector[2]; + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3] = vector[3]; //list[4 * ypos * LIGHTMAP_WIDTH + xpos] = colour } } -vec4 getLightInternal(JNIEnv *env, jobject obj, int x, int y) { +vec4 getLightInternal(jfloatArray lightmap, int x, int y) { if (y - for_y_start + overscan_open >= 0 && y - for_y_start + overscan_open < LIGHTMAP_HEIGHT && @@ -155,35 +106,25 @@ vec4 getLightInternal(JNIEnv *env, jobject obj, int x, int y) { int ypos = y - for_y_start + overscan_open int xpos = x - for_x_start + overscan_open - // get the array - jclass cls = (*env)->GetObjectClass(env, obj); - jfieldID fid = (*env)->GetFieldID(env, cls, "lightmap", "F"); - jfloat * list = (*env)->GetFloatArrayElements(env, jfloatarray, null); - - float r = list[4 * (ypos * LIGHTMAP_WIDTH + xpos)]; - float g = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1]; - float b = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2]; - float a = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3]; + float r = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos)]; + float g = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1]; + float b = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2]; + float a = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3]; // TODO check rgba argument order (RGBA or ABGR, intel doc is confusing) return _mm_set_ps(r, g, b, a); } } -JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI(JNIEnv *env, jobject object) { - // update (read) variables - jclass cls = (*env)->GetObjectClass(env, object); - jfieldID fid = (*env)->GetFieldID(env, cls, "LIGHTMAP_WIDTH", "I"); - LIGHTMAP_WIDTH = (*env)->GetIntField(env, obj, fid); - fid = (*env)->GetFieldID(env, cls, "for_x_start", "I"); - for_x_start = (*env)->GetIntField(env, obj, fid); - fid = (*env)->GetFieldID(env, cls, "for_y_start", "I"); - for_y_start = (*env)->GetIntField(env, obj, fid); - fid = (*env)->GetFieldID(env, cls, "for_x_end", "I"); - for_x_end = (*env)->GetIntField(env, obj, fid); - fid = (*env)->GetFieldID(env, cls, "for_y_end", "I"); - for_y_end = (*env)->GetIntField(env, obj, fid); +JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI + (JNIEnv * env, jobject object, jint forxstart, jint forxend, jint forystart, jint foryend, jint lighmapwidth, jint lightmapheight, jfloatArray lightmap, jintArray groundmap, jfloatArray lummap, jfloatArray shademap, jbyteArray fluidtypemap, jfloatArray fluidfillmap, jfloatArray sun) { // update (read) variables + LIGHTMAP_WIDTH = lightmapwidth; + LIGHTMAP_HEIGHT = lightmapheight; + for_x_start = forxstart; + for_x_end = forxend; + for_y_start = forystart; + for_y_end = foryend; /** * Updating order: @@ -200,7 +141,10 @@ JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fi * But why start from 2? No special reason. */ - + // clear the lightmap + for (size_t i = 0; i < sizeof(lightmap) / sizeof(lightmap[0]); i++) { + lightmap[i] = 0f; + } return; } diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt index 77fc353bf..406ee8a0d 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt @@ -82,7 +82,7 @@ object LightmapRenderer { */ // it utilises alpha channel to determine brightness of "glow" sprites (so that alpha channel works like UV light) //private val lightmap: Array> = Array(LIGHTMAP_HEIGHT) { Array(LIGHTMAP_WIDTH, { Color(0f,0f,0f,0f) }) } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4. - private val lightmap: Array = Array(LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 4) { 0f } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4. + private val lightmap: FloatArray = FloatArray(LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 4) { 0f } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4. private val lanternMap = HashMap((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4) private lateinit var texturedLightMap: FrameBuffer @@ -224,7 +224,7 @@ object LightmapRenderer { * @param colour Color to write * @param applyFun A function ```foo(old_colour, given_colour)``` */ - private fun setLightOf(list: Array, x: Int, y: Int, colour: Color) { + private fun setLightOf(list: FloatArray, x: Int, y: Int, colour: Color) { if (y - for_y_start + overscan_open in 0 until LIGHTMAP_HEIGHT && x - for_x_start + overscan_open in 0 until LIGHTMAP_WIDTH) { @@ -361,7 +361,16 @@ object LightmapRenderer { } - private external fun fireRecalculateEventJNI() + private external fun fireRecalculateEventJNI( + for_x_start: Int, for_x_end: Int, for_y_start: Int, for_y_end: Int, + lightmapwidth: Int, lightmapheight: Int, lightmap: FloatArray, + groundmap: IntArray, // high 16 bits: ground, low 16 bits: terrain + lummap: FloatArray, // interleaved RGBA + shademap: FloatArray, // interleaved RGBA + fluidtypemap: ByteArray, // 127 different fluids + fluidfillmap: FloatArray, + sun: FloatArray + ) diff --git a/src/net/torvald/terrarum/worlddrawer/net_torvald_terrarum_worlddrawer_LightmapRenderer.h b/src/net/torvald/terrarum/worlddrawer/net_torvald_terrarum_worlddrawer_LightmapRenderer.h index 912d6117b..c1e49e3df 100644 --- a/src/net/torvald/terrarum/worlddrawer/net_torvald_terrarum_worlddrawer_LightmapRenderer.h +++ b/src/net/torvald/terrarum/worlddrawer/net_torvald_terrarum_worlddrawer_LightmapRenderer.h @@ -48,10 +48,10 @@ extern "C" { /* * Class: net_torvald_terrarum_worlddrawer_LightmapRenderer * Method: fireRecalculateEventJNI - * Signature: ()V + * Signature: (IIIIII[F[I[F[F[B[F[F)V */ JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI - (JNIEnv *, jobject); + (JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jfloatArray, jintArray, jfloatArray, jfloatArray, jbyteArray, jfloatArray, jfloatArray); #ifdef __cplusplus }