c++ - 无法在 native 代码中使用 jstring 作为参数

标签 c++ android-ndk java-native-interface artoolkit

我需要在我的 native 代码中使用 const char * 所以,我将 java 端的参数作为 jstring 并使用以下语句

JNIEXPORT int JNICALL JNIFUNCTION_DEMO(AddMarkerAndModel(JNIEnv* env, jobject object, jstring modelfileString , jstring marker_config_string)) {

    int free_marker_space_index=-1;

    for (int i = 0; i < NUM_MODELS; i++) {
        if (models[i].not_null==false) {
            free_marker_space_index = i;
            break;
        }
    }
    if(free_marker_space_index==-1){
        //means no space for marker left
        return free_marker_space_index;
    }
    const char *marker_config = env->GetStringUTFChars( marker_config_string, NULL);
    LOGE("[KARTIK]marker_config is : %s",marker_config);

    models[free_marker_space_index].patternID = arwAddMarker(marker_config);


    arwSetMarkerOptionBool(models[free_marker_space_index].patternID, ARW_MARKER_OPTION_SQUARE_USE_CONT_POSE_ESTIMATION, false);
    arwSetMarkerOptionBool(models[free_marker_space_index].patternID, ARW_MARKER_OPTION_FILTERED, true);

    const char *modelfile = env->GetStringUTFChars( modelfileString, NULL);
    LOGE("[KARTIK]modelFile is : %s",modelfile);
    models[free_marker_space_index].obj = glmReadOBJ2(modelfile, 0, 0); // context 0, don't read textures yet.
    if (!models[free_marker_space_index].obj) {
        LOGE("Error loading model from file '%s'.", modelfile);
        exit(-1);
    }
//  LOGV("just checking this function..no error..don't worry");
    //printf("just checking this function..no error..don't worry");
    glmScale(models[free_marker_space_index].obj, 0.035f);
    //glmRotate(models[0].obj, 3.14159f / 2.0f, 1.0f, 0.0f, 0.0f);
    glmCreateArrays(models[free_marker_space_index].obj, GLM_SMOOTH | GLM_MATERIAL | GLM_TEXTURE);
    models[free_marker_space_index].visible = false;
    models[free_marker_space_index].not_null=true;

    //LOGV("ReleaseStringUTFChars");
    env->ReleaseStringUTFChars(modelfileString, modelfile);
    env->ReleaseStringUTFChars(marker_config_string, marker_config);    


    return free_marker_space_index;
}

这个函数说无法读取代码在 glm.c 中的 mtl 文件..它的一部分在下面......看看 ReadOBJ 和 ReadMTL 函数

#include <Eden/glm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <limits.h>             // USHRT_MAX
#include <Eden/EdenMath.h>      // M_PI, sqrtf(), acosf(), asinf(), fabsf()
#ifndef EDEN_OPENGLES
#  define DISABLE_GL_STATE_CACHE
#endif
#include "glStateCache.h"
#ifndef GL_GENERATE_MIPMAP
#  define GL_GENERATE_MIPMAP 0x8191
#endif

#define glmDefaultGroupName "default"
#define T(x) (model->triangles[(x)])

/* _GLMnode: general purpose node, used by glmVertexNormals() to build a
    linked list of triangles containing a particular vertex. */
typedef struct _GLMnode {
    GLuint          index;      // Which triangle this node is tracking.
    GLuint          indexindex; // Which of the points in this triangle this node is tracking.
    GLboolean       averaged;
    struct _GLMnode* next;      // The next node in the list, or NULL if this node is the tail.
} GLMnode;

/* _GLMnode: general purpose node, used by glmDrawArrays() to build a
 linked list of triangles containing a particular vertex. */
typedef struct _GLMnode2 {
    GLushort          index; // Index into list of per-vertex data values. Each 3 defines a triangle.
    struct _GLMnode2* next;     // The next node in the list, or NULL if this node is the tail.
} GLMnode2;

#define glmMax(a, b) ((a) > (b) ? (a) : (b))
#define glmMin(a, b) ((a) < (b) ? (a) : (b))


/* glmFindMaterial: Find a material in the model */
static GLuint glmFindMaterial(GLMmodel* model, char* name)
{
    GLuint i;

    /* XXX doing a linear search on a string key'd list is pretty lame,
    but it works and is fast enough for now. */
    for (i = 0; i < model->nummaterials; i++) {
        if (!strcmp(model->materials[i].name, name))
            goto found;
    }

    /* didn't find the name, so print a warning and return the default
    material (0). */
    EDEN_LOGe("glmFindMaterial():  can't find material \"%s\".\n", name);
    i = 0;

found:
    return i;
}

/* glmDirName: return the directory given a path
 *
 * path - filesystem path
 *
 * NOTE: the return value should be free'd.
 */
static char*
glmDirName(char* path)
{
    char* dir;
    char* s;

    dir = strdup(path);

    s = strrchr(dir, '/');
    if (s)
        s[1] = '\0';    // place end of string after last separator
    else
        dir[0] = '\0';

    return dir;
}

#ifdef GLM_MATERIAL_TEXTURES
static GLboolean readTextureAndSendToGL(const int contextIndex, char *texturefilename, TEXTURE_INDEX_t *texturemap_index, char *texturemap_hasAlpha, const GLboolean flipH, const GLboolean flipV)
{
    TEXTURE_INFO_t textureInfo = {      // PRL 2003-08-06: Defaults for texturemaps.
        NULL,                           //   pointer to name will go here.
        GL_TRUE,                        //   generate mipmaps.
        0,                              //   internal format (0 = don't attempt conversion).
        GL_LINEAR_MIPMAP_LINEAR,        //   minification mode.
        GL_LINEAR,                      //   magnification mode.
        GL_REPEAT,                      //   wrap_s.
        GL_REPEAT,                      //   wrap_t.
        0.5,                            //   priority.
        GL_REPLACE,                     //   env_mode.
        //{0.0,0.0,0.0,0.0}             //   env_color.
    };
    static char initedSurfaces = FALSE;

    textureInfo.pathname = texturefilename;
    if (!initedSurfaces) {
        EdenSurfacesInit(1, 256); // Up to 256 textures, into 1 OpenGL context.
        initedSurfaces = TRUE;
    }
    if (!EdenSurfacesTextureLoad2(contextIndex, 1, &textureInfo, texturemap_index, texturemap_hasAlpha, flipH, flipV)) {
        EDEN_LOGe("EdenSurfacesTextureLoad() couldn't read texture file \"%s\".\n", texturefilename);
        return (FALSE);
    }
    return (TRUE);
}
#endif // GLM_MATERIAL_TEXTURES

/* glmReadMTL: read a wavefront material library file
 *
 * model - properly initialized GLMmodel structure
 * name  - name of the material library
 * contextIndex - PRL: index to the current OpenGL context (for texturing.) If you have only
 *             one OpenGL context (the most common case) set this parameter to 0.
 */
static GLboolean
glmReadMTL(GLMmodel* model, char* name, const int contextIndex, const GLboolean readTexturesNow)
{
    FILE* file;
    char* dir;
    char* filename;
    char    buf[128];
    GLuint nummaterials, i;

    dir = glmDirName(model->pathname);
    filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));
    strcpy(filename, dir);
    strcat(filename, name);
    free(dir);

    file = fopen(filename, "r");
    if (!file) {
        EDEN_LOGe("glmReadMTL() failed: can't open material file \"%s\".\n", filename);
        return (FALSE);
    }

    /* count the number of materials in the file */
    nummaterials = 1; // default material 0 is always defined.
    while(fscanf(file, "%s", buf) != EOF) {
        switch(buf[0]) {
        case '#':               /* comment */
            /* eat up rest of line */
            fgets(buf, sizeof(buf), file);
            break;
        case 'n':               /* newmtl */
            fgets(buf, sizeof(buf), file);
            nummaterials++;
            //sscanf(buf, "%s %s", buf, buf);
            break;
        default:
            /* eat up rest of line */
            fgets(buf, sizeof(buf), file);
            break;
        }
    }

    rewind(file);

    model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials);
    model->nummaterials = nummaterials;

    /* set the defaults for each material */
    for (i = 0; i < nummaterials; i++) {
        model->materials[i].name = NULL;
        model->materials[i].shininess = 65.0;
        model->materials[i].diffuse[0] = 0.8;
        model->materials[i].diffuse[1] = 0.8;
        model->materials[i].diffuse[2] = 0.8;
        model->materials[i].diffuse[3] = 1.0; // Opaque.
        model->materials[i].ambient[0] = 0.2;
        model->materials[i].ambient[1] = 0.2;
        model->materials[i].ambient[2] = 0.2;
        model->materials[i].ambient[3] = 1.0;
        model->materials[i].specular[0] = 0.0;
        model->materials[i].specular[1] = 0.0;
        model->materials[i].specular[2] = 0.0;
        model->materials[i].specular[3] = 1.0;
#ifdef GLM_MATERIAL_TEXTURES
        model->materials[i].texturemap = NULL;      // PRL 20030806: No texture by default.
        model->materials[i].texturemappath = NULL;
        model->materials[i].texturemap_index = (TEXTURE_INDEX_t)0;
        model->materials[i].texturemap_hasAlpha = 0;
#endif // GLM_MATERIAL_TEXTURES
        model->materials[i].illum = 2; // Is 2 the default?
    }
    model->materials[0].name = strdup("default");

    /* now, read in the data */
    nummaterials = 0;
    while(fscanf(file, "%s", buf) != EOF) {
        switch(buf[0]) {
            case '#':               /* comment */
                /* eat up rest of line */
                fgets(buf, sizeof(buf), file);
                break;
            case 'n':               /* newmtl */
                fgets(buf, sizeof(buf), file);
                sscanf(buf, "%s %s", buf, buf);
                nummaterials++;
                model->materials[nummaterials].name = strdup(buf);
                break;
            case 'N':
                switch (buf[1]) {
                    case 's':
                        fscanf(file, "%f", &model->materials[nummaterials].shininess);
                        /* wavefront shininess is from [0, 1000], so scale to [0, 127] for OpenGL */
                        model->materials[nummaterials].shininess /= 1000.0;
                        model->materials[nummaterials].shininess *= 128.0;
                        break;
                    default:
                        // Unsupported options:
                        // Ni = Refraction index. Values range from 1 upwards. A value of 1 will cause no refraction. A higher value implies refraction.
                        fgets(buf, sizeof(buf), file);
                        break;
                }
                break;
            case 'K':
                switch(buf[1]) {
                    case 'd':
                        fscanf(file, "%f %f %f",
                            &model->materials[nummaterials].diffuse[0],
                            &model->materials[nummaterials].diffuse[1],
                            &model->materials[nummaterials].diffuse[2]);
                        break;
                    case 's':
                        fscanf(file, "%f %f %f",
                            &model->materials[nummaterials].specular[0],
                            &model->materials[nummaterials].specular[1],
                            &model->materials[nummaterials].specular[2]);
                        break;
                    case 'a':
                        fscanf(file, "%f %f %f",
                            &model->materials[nummaterials].ambient[0],
                            &model->materials[nummaterials].ambient[1],
                            &model->materials[nummaterials].ambient[2]);
                        break;
                    default:
                        /* eat up rest of line */
                        fgets(buf, sizeof(buf), file);
                        break;
                }
                break;
            case 'd':       // PRL 20030806: dissolve factor, pseudo-transparency.
                fscanf(file, "%f", &model->materials[nummaterials].diffuse[3]);
                break;
#ifdef GLM_MATERIAL_TEXTURES
            case 'm':       // PRL 20030806: texturemap.
                if (strstr(buf, "map_Kd")) { // Process diffuse colour map.
                    fgets(buf, sizeof(buf), file);      // Read up to (and including) EOL from file into string.
                    buf[strlen(buf)-1] = '\0';          // nuke '\n'.
                    model->materials[nummaterials].texturemap = strdup(buf+1);  // Save relative path from mtl file. +1 skips leading space.
                    // Handle relative paths from model and material.
                    dir = glmDirName(filename);
                    model->materials[nummaterials].texturemappath = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(model->materials[nummaterials].texturemap) + 1));
                    strcpy(model->materials[nummaterials].texturemappath, dir);
                    strcat(model->materials[nummaterials].texturemappath, model->materials[nummaterials].texturemap);
                    free(dir);
                    if (readTexturesNow) {
                        if (!readTextureAndSendToGL(contextIndex, model->materials[nummaterials].texturemappath, &(model->materials[nummaterials].texturemap_index), &(model->materials[nummaterials].texturemap_hasAlpha), FALSE, model->flipTextureV)) {
                            EDEN_LOGe("glmReadMTL(): Error loading texture.\n");
                        }
                    }
                } else {
                    // Unsupported options:
                    // map_Ka, ambient colour map.
                    // map_Ks, specular colour map.
                    fgets(buf, sizeof(buf), file);      // eat up rest of line.
                }
                break;
#endif // GLM_MATERIAL_TEXTURES
            case 'i':       // Illumination model.
                fscanf(file, "%d", &model->materials[nummaterials].illum);
                break;
            default:
                /* eat up rest of line */
                fgets(buf, sizeof(buf), file);
                break;
        }
    }
    free(filename);
    return (TRUE);
}

/* glmWriteMTL: write a wavefront material library file
 *
 * model   - properly initialized GLMmodel structure
 * modelpath  - pathname of the model being written
 * mtllibname - name of the material library to be written
 */
static GLvoid
glmWriteMTL(GLMmodel* model, char* modelpath, char* mtllibname)
{
    FILE* file;
    char* dir;
    char* filename;
    GLMmaterial* material;
    GLuint i;

    dir = glmDirName(modelpath);
    filename = (char*)malloc(sizeof(char) * (strlen(dir)+strlen(mtllibname)));
    strcpy(filename, dir);
    strcat(filename, mtllibname);
    free(dir);

    /* open the file */
    file = fopen(filename, "w");
    if (!file) {
        EDEN_LOGe("glmWriteMTL() failed: can't open file \"%s\".\n",
            filename);
        exit(1);
    }
    free(filename);

    /* spit out a header */
    fprintf(file, "#  \n");
    fprintf(file, "#  Wavefront MTL generated by GLM library\n");
    fprintf(file, "#  \n");
    fprintf(file, "#  GLM library\n");
    fprintf(file, "#  Nate Robins\n");
    fprintf(file, "#  ndr@pobox.com\n");
    fprintf(file, "#  http://www.pobox.com/~ndr\n");
    fprintf(file, "#  \n\n");

    for (i = 0; i < model->nummaterials; i++) {
        material = &model->materials[i];
        fprintf(file, "newmtl %s\n", material->name);
        fprintf(file, "Ka %f %f %f\n", 
            material->ambient[0], material->ambient[1], material->ambient[2]);
        fprintf(file, "Kd %f %f %f\n", 
            material->diffuse[0], material->diffuse[1], material->diffuse[2]);
        fprintf(file, "Ks %f %f %f\n", 
            material->specular[0],material->specular[1],material->specular[2]);
        fprintf(file, "Ns %f\n", material->shininess / 128.0 * 1000.0);
        if (material->diffuse[3] != 1.0) fprintf(file, "d %f\n", material->diffuse[3]); // PRL 20030806: dissolve factor, pseudo-transparency.
#ifdef GLM_MATERIAL_TEXTURES
        if (material->texturemap) fprintf(file, "map_Kd %s\n", material->texturemap); // PRL 20030806: texturemap.
#endif // GLM_MATERIAL_TEXTURES
        fprintf(file, "illum %d\n", material->illum);
        fprintf(file, "\n");
    }
}

static void trim(char *buf)
{
    size_t index;

    if (!buf) return;

    index = strlen(buf);
    if (!index) return;
    index--;

    // Strip trailing CR and NL chars.
    while (index && (buf[index] == '\r' || buf[index] == '\n')) {
        buf[index] = '\0';
        index--;
    }
}


GLMmodel*
glmReadOBJ(const char *filename, const int contextIndex)
{
    return (glmReadOBJ3(filename, contextIndex, TRUE, FALSE));
}

GLMmodel*
glmReadOBJ2(const char *filename, const int contextIndex, const GLboolean readTexturesNow)
{
    return (glmReadOBJ3(filename, contextIndex, readTexturesNow, FALSE));
}

GLMmodel*
glmReadOBJ3(const char *filename, const int contextIndex, const GLboolean readTexturesNow, const GLboolean flipTextureV)
{
    GLMmodel* model;
    FILE*   file;

    /* open the file */
    file = fopen(filename, "r");
    if (!file) {
        EDEN_LOGe("glmReadOBJ() failed: can't open data file \"%s\".\n", filename);
        return (NULL);
    }

    /* allocate a new model */
    model = (GLMmodel*)malloc(sizeof(GLMmodel));
    model->pathname     = strdup(filename);
    model->mtllibname   = NULL;
    model->numvertices  = 0;
    model->vertices     = NULL;
    model->numnormals   = 0;
    model->normals      = NULL;
    model->numtexcoords = 0;
    model->texcoords    = NULL;
    model->numfacetnorms    = 0;
    model->facetnorms   = NULL;
    model->numtriangles = 0;
    model->triangles    = NULL;
    model->nummaterials = 0;
    model->materials    = NULL;
    model->numgroups    = 0;
    model->groups       = NULL;
    model->arrays       = NULL;
    model->arrayMode    = 0;
    model->readTextureRequired = !readTexturesNow;
    model->flipTextureV        = flipTextureV;

    /* make a first pass through the file to get a count of the number
    of vertices, normals, texcoords & triangles */
    glmFirstPass(model, file, contextIndex, readTexturesNow);

    /* allocate memory */
    model->vertices = (GLfloat*)malloc(sizeof(GLfloat) *
        3 * (model->numvertices + 1));          // Uses + 1 because vertices, normals and texcoords are numbered from 1, not 0.
    model->triangles = (GLMtriangle*)malloc(sizeof(GLMtriangle) *
        model->numtriangles);
    if (model->numnormals) {
        model->normals = (GLfloat*)malloc(sizeof(GLfloat) *
            3 * (model->numnormals + 1));       // Uses + 1 because vertices, normals and texcoords are numbered from 1, not 0.
    }
    if (model->numtexcoords) {
        model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) *
            2 * (model->numtexcoords + 1));     // Uses + 1 because vertices, normals and texcoords are numbered from 1, not 0.
    }

    /* rewind to beginning of file and read in the data this pass */
    rewind(file);

    glmSecondPass(model, file);

    /* close the file */
    fclose(file);

    return model;
}

但是,下面的代码片段有效

JNIEXPORT void JNICALL JNIFUNCTION_DEMO(Initialise(JNIEnv* env, jobject object)) {



    for(int i=0;i<NUM_MODELS;i++){

            models[i].patternID=-1;
    //      models[i].transformationMatrix=PUT_SOME_PLACEHOLDER_TEMPORARY_VARIABLE_HERE;
            models[i].visible=false;
            models[i].obj=NULL;
            models[i].not_null=false;
         //mean they are null ...
    }
    const char *model1file = "Data/models/pinball/Ferrari_Modena_Spider.obj";
    models[0].patternID = arwAddMarker("nft;DataNFT/pinball");
    arwSetMarkerOptionBool(models[0].patternID, ARW_MARKER_OPTION_SQUARE_USE_CONT_POSE_ESTIMATION, false);
    arwSetMarkerOptionBool(models[0].patternID, ARW_MARKER_OPTION_FILTERED, true);

    models[0].obj = glmReadOBJ2(model1file, 0, 0); // context 0, don't read textures yet.
    if (!models[0].obj) {
        LOGE("Error loading model from file '%s'.", model1file);
        exit(-1);
    }
    glmScale(models[0].obj, 0.035f);
    //glmRotate(models[0].obj, 3.14159f / 2.0f, 1.0f, 0.0f, 0.0f);
    glmCreateArrays(models[0].obj, GLM_SMOOTH | GLM_MATERIAL | GLM_TEXTURE);
    models[0].visible = false;
    models[0].not_null = true;

    LOGE("trying to add a marker in Initialise");

}

唯一的区别似乎是,在初始化中,我对路径进行了硬编码....但在 addMarkerandModel 中...我将它们作为通过 jni 传递的参数提供

请帮忙!!!!

最佳答案

在 ARToolKit 的 glm 中读取 .obj 文件分几步进行。首先,解析 .obj 文件,然后加载任何引用的 .mtl 文件,最后,如果 .mtl 文件引用纹理(ARToolKit 的 glm 阅读器仅支持二次方大小的 .sgi 和 JPEG),然后一旦 OpenGL 上下文可用,它们就会延迟加载。

如果您遇到无法找到 .mtl 文件的错误,则表明第一步实际上是正确的。 glm 能够找到并读取 .obj 文件,但 .obj 文件引用了一个找不到的 .mtl 文件。

在文本编辑器中浏览您的 .obj 文件,找到所有 .mtl 引用,并编辑它们以便引用正确的相对路径。

关于c++ - 无法在 native 代码中使用 jstring 作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43842215/

相关文章:

Android,如何在 "ndk-build"中使用 fipsld for openssl

java - 使用 jna.jar 和 platform.jar 出现 NoClassDefFoundError

android-ndk - 无法将库从 Windows 交叉编译到 Android

c++ - g++ 链接静态库

c++ - OMP : How to find the right size of cache at runtime

c++ - 如何使用 set<pair<int,int>>::iterator 迭代 set<pair<int,int>>st 中的值?

java - 如何将 C 实现的 JNI( native )方法的输出返回到 Java

c++ - 在 C++ 中读取每行 2 个数字

android - 最大的相机抓取和显示性能

c++ - stringstream << 运算符在循环中消耗大量内存