mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
instead of frequently accessing Java from C-side, feed everything beforehand on Java-side
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
#include <xmmintrin.h>
|
||||
#include <jni.h>
|
||||
#include <stddef.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -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<Color>> = 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<Float> = 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<BlockAddress, Color>((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<Float>, 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
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user