Log in or register to post comments

Convert .obj to .h

January 9, 2013 - 7:45am #39

Hello everyone; I tried to change ImageTargets 3d models. I have models which are .blend and .obj . I want to convert them to .h and put the ImageTargets project in place of Teapot.h. So I hope see my new 3d model on my phone screen.

I found document in http://heikobehrens.net/2009/08/27/obj2opengl/ . I downloaded OBJ2OPENGL.ZIP (script and examples). but  i can not understand how run obj2opengl.pl and import my object x.obj . In foler I can see banana.obj and banana.h. How can i do this?

You need to open a command

January 9, 2013 - 8:01am #38

You need to open a command console, switch to the obj2opengl script directory and then type:

obj2opengl.pl   your_model.obj

This will produce a file called your_model.h

You can also use some additional options, for instance to scale the model by a factor 4 you could type:

obj2opengl.pl your_model.obj -s 4

 

IHTH.

 

I run the cmd and go to

January 9, 2013 - 8:52am #37

when i write obj2opengl.pl   your_model.obj in cmd i can create my model's .h file. But when i changed files with Teapot.h and change my model's name with Teapot.h. But I take some errors and  can not compile sample. How can i import my model in place of Teapod.h ?

Renaming the file to Teapot.h

January 9, 2013 - 9:51am #36

Renaming the file to Teapot.h is not sufficient (and not necessary);

you should just add an #include "mymodel.h" in ImageTargets.cpp and then you need to rename the names of the mesh vertices and texture coordinates in the code:

have a look at here for a detailed step by step explanation:

https://developer.vuforia.com/forum/faq/android-how-do-i-replace-teapot

 

I can not understant clearly.

January 9, 2013 - 11:22am #35

I can not understant clearly. I included myobject.h and change the names in imagetargets.cpp. For example;

#include "myobject.h"

 

           // Draw object:
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) &myobjectTexCoords[0]);
        glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &myobjectVertices[0]);
        glNormalPointer(GL_FLOAT, 0,  (const GLvoid*) &myobjectNormals[0]);
 I changed all code like this. But I took errors cygwin when ı tried to compile it. What is my fault?

I can not understant clearly.

January 9, 2013 - 1:44pm #34

I can not understant clearly. I included myobject.h and change the names in imagetargets.cpp. For example;

#include "myobject.h"

 

           // Draw object:
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) &myobjectTexCoords[0]);
        glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &myobjectVertices[0]);
        glNormalPointer(GL_FLOAT, 0,  (const GLvoid*) &myobjectNormals[0]);
 I changed all code like this. But I took errors cygwin when ı tried to compile it. What is my fault?

Hi, you should open the

January 9, 2013 - 10:51pm #33

Hi, you should open the myobject.h file and check the exact names of those arrays; for example it is likely that the vertex array is called something like "myobjectVerts" instead of "myObjectVertices"; also, check if the texcoord and the normals are both defined in that file (if not you need to either re-export the OBJ from your editor so that it contains bith texture coords and normals, or you need to comment out the GL code that uses them);

to make it simpler, can you copy-paste here the errors you get from Cygwin ?

 

Hi I can change teapot to

January 10, 2013 - 12:49pm #32

Hi I can change teapot to different object. I used banana model which is include in http://heikobehrens.net/2009/08/27/obj2opengl/ examples.

Firstly I changed ImageTargets.java and I add

mTextures.add(Texture.loadTextureFromApk("banana.png", getAssets()));

in loadTextures() and add banana.png in assets folder.

After that I changed ImageTargets.cpp like this:

 

// Draw object:
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) &teapotTexCoords[0]);
        glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &teapotVertices[0]);
        glNormalPointer(GL_FLOAT, 0,  (const GLvoid*) &teapotNormals[0]);
        glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT,
                       (const GLvoid*) &teapotIndices[0]);
to
 
// Draw object:
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glVertexPointer(3, GL_FLOAT, 0, bananaVerts);
        glNormalPointer(GL_FLOAT, 0, bananaNormals);
        glTexCoordPointer(2, GL_FLOAT, 0, bananaTexCoords);
        glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);

Also;

 

        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &teapotVertices[0]);
        glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &teapotNormals[0]);
        glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &teapotTexCoords[0]);
        glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &teapotIndices[0]);

 

to
        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &bananaVerts[0]);
        glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &bananaNormals[0]);
        glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &bananaTexCoords[0]);
        glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);
 
It works correctly thanks for help AllessendroB. Only problem is,banana is shown in phone screen very high to marker.  But its ready model and banana.h includes vertices, textcoordinates and normals. I create 3d model in blender and export  .obj format. After that convert it with obj2opengl.pl myobject.obj code in cmd. It create myobject.h but it has not texture. ıt has only normals and vertices. Also I have not myobject.png. I guess for import 3d model to imageTargets projects I should have to. How can i solve this problem? By the way I really thank you for your help. I know I'm beginner and do something not easily but you help me everytime. Thankyou
 

 

Hi, happy to hear that you

January 10, 2013 - 2:44pm #31

Hi, happy to hear that you made it work.

For the texture coordinates, you should choose an image that you want to apply to your 3D model and then try to create UV-map coordinates for your model in Blender,

and then export it to OBJ with the texture coordinates;

this thread discusses some technique to to that in Blender:

http://gamedev.stackexchange.com/questions/16136/blender-exporting-obj-with-texture-coords

I hope this helps.

I can create texture with

January 11, 2013 - 9:35am #30

I can create texture with link and ı can import my object and see in imagetargets . but still i can not create myobject.png. I hope find it. My other question is about markers. With using target manager, i upload a image. After that download it. Now i have img.dat and img.xml . I changed thats name with Tarmac. I put them in assets folder. But when i compile imagetargets, my image can not run. My Tarmac.xml code is:

 

<?xml version="1.0" encoding="UTF-8"?>
<QCARConfig>
    <Tracking>
        <ImageTarget size="945 945" name="tarmac"/>
    </Tracking>
</QCARConfig>
 I tried to put up tarmac marker with my new image. But it doesnt work. How can i solve this problem? or how can i add new marker? What is wrong

Hi, renaming the DataSets

January 11, 2013 - 11:17am #29

Hi, renaming the DataSets and/or target does not work;

what you need to do is to create a Database (using the TMS) with the right name;

if you already have created one Database and you don't want to create a new one, you can also just rename the Database with the TMS (there is a Rename function in the Web TMS); but that must be done in the TMS (i.e. before downloading to file);

same for the name of the targets inside the Database;

so in your example, you need to login into the Web TMS, create a Database called Tarmac (or rename the one you already have to "Tarmac"), then you need to also rename the Image Target in that Database to "tarmac".

Alternatively, you can just change the ImageTargets sample code to use the actual names of your Database and target image.

 

 

I created database with

January 12, 2013 - 4:37am #28

Sorry I can do it. The problem was my image. I tried to add cloud and see image take zero star. I changed my image and it run thank you

Glad to hear that you solved

January 13, 2013 - 6:37am #27

Glad to hear that you solved it.

Convert .obj to .h

March 11, 2013 - 11:00pm #26

Im open command console :

 

obj2opengl.pl banana.obj

But, it is not create file .h

This command suppor Linux or Window or both ?

I'm using Window

Convert .obj to .h

March 12, 2013 - 12:53am #25

I tested the tool in Windows, but it's just a Perl script and it should run on Linux as well;

you may need to install a Perl script interpreter though.

When you run it, you should see a Log similar to the following:

 

C:\Development\Tools\obj2opengl>obj2opengl.pl banana.obj
defined(@array) is deprecated at C:\Development\Tools\obj2opengl\obj2opengl.pl line 154.
        (Maybe you should just omit the defined()?)
Input file     : .\banana.obj
Output file    : .\banana.h
Object name    : banana
Center         : <2289.89534195908, 599.62239347371, -8421.71066976487>
Scale by       : 0.000175074008952644
----------------
Vertices       : 4032
Faces          : 8056
Texture Coords : 4420
Normals        : 4032

HTH.

Convert .obj to .h

March 12, 2013 - 7:12am #24

Hi phant0m,

I'm use file banana.h to http://heikobehrens.net/2009/08/27/obj2opengl/

Then i copy file banana.h into sample Image taget. In file ImageTargets.cpp. I add banana.png into forlder assets

Function my loadTextures():

 private void loadTextures()

  {
     mTextures.add(Texture.loadTextureFromApk("banana.png", getAssets()));

 } 

#include <banana.h>

Replace : 

 

// Draw object:
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) &teapotTexCoords[0]);
        glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &teapotVertices[0]);
        glNormalPointer(GL_FLOAT, 0,  (const GLvoid*) &teapotNormals[0]);
        glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT,
                       (const GLvoid*) &teapotIndices[0]);
to
 
// Draw object:
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glVertexPointer(3, GL_FLOAT, 0, bananaVerts);
        glNormalPointer(GL_FLOAT, 0, bananaNormals);
        glTexCoordPointer(2, GL_FLOAT, 0, bananaTexCoords);
        glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);

 

 

Also;

 

        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &teapotVertices[0]);
        glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &teapotNormals[0]);
        glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &teapotTexCoords[0]);
        glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &teapotIndices[0]);

 

to
        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &bananaVerts[0]);
        glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &bananaNormals[0]);
        glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) &bananaTexCoords[0]);
        glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);
But, model 3D banana no display on  phone's screen 
Can you help me ?

 

Convert .obj to .h

March 12, 2013 - 11:19pm #23

 

Hi phant0m

1) In ImageTargets.cpp change this line:

              static const float kObjectScale = 3.f;

I'm changed  kObjectScale =100;

    static const float kObjectScale = 100

It was show phone's screen . But,it is not show as file 3D banana .

Here, Images to phone's screen :

http://nv8.upanh.com/b2.s33.d3/03fb68e585032b098b9449a17be97d21_53942158.13032013406.jpg

http://nv9.upanh.com/b1.s35.d3/e1f39d23a7eca81dbc84673d606726d8_53942159.13032013407.jpg

http://nv1.upanh.com/b3.s32.d1/f9f4f14e026dd19101eb3ce90c2d99fe_53942161.13032013408.jpg

My Project :

http://www.mediafire.com/?m615tnaldmt7yys

Convert .obj to .h

March 13, 2013 - 2:52am #22

Hi, if it can help, I'm pasting here the whole renderFrame() function that I use to show the banana.h model (and this works, provided that kObjectScale is set to 100):

JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_renderFrame(JNIEnv *, jobject)
{
	//LOG("Java_com_qualcomm_QCARSamples_ImageTargets_GLRenderer_renderFrame");

    // Clear color and depth buffer 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Get the state from QCAR and mark the beginning of a rendering section
    QCAR::State state = QCAR::Renderer::getInstance().begin();
    
    // Explicitly render the Video Background
    QCAR::Renderer::getInstance().drawVideoBackground();

    glEnable(GL_DEPTH_TEST);

    // We must detect if background reflection is active and adjust the culling direction. 
    // If the reflection is active, this means the post matrix has been reflected as well,
    // therefore standard counter clockwise face culling will result in "inside out" models. 
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    if(QCAR::Renderer::getInstance().getVideoBackgroundConfig().mReflection == QCAR::VIDEO_BACKGROUND_REFLECTION_ON)
        glFrontFace(GL_CW);  //Front camera
    else
        glFrontFace(GL_CCW);   //Back camera


    // Did we find any trackables this frame?
    for(int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
    {
        // Get the trackable:
        const QCAR::TrackableResult* result = state.getTrackableResult(tIdx);
        const QCAR::Trackable& trackable = result->getTrackable();

        QCAR::Matrix44F modelViewMatrix =
            QCAR::Tool::convertPose2GLMatrix(result->getPose());


        // Choose the texture based on the target name:
        int textureIndex;
        if (strcmp(trackable.getName(), "chips") == 0)
        {
            textureIndex = 0;
        }
        else if (strcmp(trackable.getName(), "stones") == 0)
        {
            textureIndex = 1;
        }
        else
        {
            textureIndex = 2;
        }

        const Texture* const thisTexture = textures[textureIndex];

        QCAR::Matrix44F modelViewProjection;

        SampleUtils::translatePoseMatrix(0.0f, 0.0f, kObjectScale,
                                         &modelViewMatrix.data[0]);
        SampleUtils::scalePoseMatrix(kObjectScale, kObjectScale, kObjectScale,
                                     &modelViewMatrix.data[0]);

        SampleUtils::multiplyMatrix(&projectionMatrix.data[0],
                                    &modelViewMatrix.data[0] ,
                                    &modelViewProjection.data[0]);

        glUseProgram(shaderProgramID);
         

        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
                              (const GLvoid*) &bananaVerts[0]);
        glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
                              (const GLvoid*) &bananaNormals[0]);
        glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
                              (const GLvoid*) &bananaTexCoords[0]);

        
        glEnableVertexAttribArray(vertexHandle);
        glEnableVertexAttribArray(normalHandle);
        glEnableVertexAttribArray(textureCoordHandle);
        
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glUniform1i(texSampler2DHandle, 0);
        glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE,
                           (GLfloat*)&modelViewProjection.data[0] );

        glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);

        SampleUtils::checkGlError("ImageTargets renderFrame");
    }

    glDisable(GL_DEPTH_TEST);

    glDisableVertexAttribArray(vertexHandle);
    glDisableVertexAttribArray(normalHandle);
    glDisableVertexAttribArray(textureCoordHandle);

    QCAR::Renderer::getInstance().end();

}

Please compare with your code.

 

Convert .obj to .h

March 13, 2013 - 5:11pm #21

Hi AlessandroB,

I copy your code . Replace in File my Imagetargets.cpp . Then, I use cammand console : ndk-build 

 

jni/ImageTargets.cpp:371:1: error: stray '\240' in program
jni/ImageTargets.cpp:371:1: error: stray '\240' in program
jni/ImageTargets.cpp:371:1: error: stray '\240' in program
make: *** [obj/local/armeabi/objs/ImageTargets/ImageTargets.o] Error 1
C:\Development\Android\vuforia-sdk-android-2-0-31\samples\ImageTargets-2-0-7>
Here file my Imagetargets.cpp :
/*==============================================================================
            Copyright (c) 2010-2013 QUALCOMM Austria Research Center GmbH.
            All Rights Reserved.
            Qualcomm Confidential and Proprietary

@file
    ImageTargets.cpp

@brief
    Sample for ImageTargets

==============================================================================*/


#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <banana.h>

#ifdef USE_OPENGL_ES_1_1
#include <GLES/gl.h>
#include <GLES/glext.h>
#else
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif

#include <QCAR/QCAR.h>
#include <QCAR/CameraDevice.h>
#include <QCAR/Renderer.h>
#include <QCAR/VideoBackgroundConfig.h>
#include <QCAR/Trackable.h>
#include <QCAR/TrackableResult.h>
#include <QCAR/Tool.h>
#include <QCAR/Tracker.h>
#include <QCAR/TrackerManager.h>
#include <QCAR/ImageTracker.h>
#include <QCAR/CameraCalibration.h>
#include <QCAR/UpdateCallback.h>
#include <QCAR/DataSet.h>


#include "SampleUtils.h"
#include "Texture.h"
#include "CubeShaders.h"
#include "Teapot.h"

#ifdef __cplusplus
extern "C"
{
#endif

// Textures:
int textureCount                = 0;
Texture** textures              = 0;

// OpenGL ES 2.0 specific:
#ifdef USE_OPENGL_ES_2_0
unsigned int shaderProgramID    = 0;
GLint vertexHandle              = 0;
GLint normalHandle              = 0;
GLint textureCoordHandle        = 0;
GLint mvpMatrixHandle           = 0;
GLint texSampler2DHandle        = 0;
#endif

// Screen dimensions:
unsigned int screenWidth        = 0;
unsigned int screenHeight       = 0;

// Indicates whether screen is in portrait (true) or landscape (false) mode
bool isActivityInPortraitMode   = false;

// The projection matrix used for rendering virtual objects:
QCAR::Matrix44F projectionMatrix;

// Constants:
static const float kObjectScale = 3.f;

QCAR::DataSet* dataSetStonesAndChips    = 0;
QCAR::DataSet* dataSetTarmac            = 0;

bool switchDataSetAsap          = false;

// Object to receive update callbacks from QCAR SDK
class ImageTargets_UpdateCallback : public QCAR::UpdateCallback
{
    virtual void QCAR_onUpdate(QCAR::State& /*state*/)
    {
        if (switchDataSetAsap)
        {
            switchDataSetAsap = false;

            // Get the image tracker:
            QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
            QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>(
                trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER));
            if (imageTracker == 0 || dataSetStonesAndChips == 0 || dataSetTarmac == 0 ||
                imageTracker->getActiveDataSet() == 0)
            {
                LOG("Failed to switch data set.");
                return;
            }

            if (imageTracker->getActiveDataSet() == dataSetStonesAndChips)
            {
                imageTracker->deactivateDataSet(dataSetStonesAndChips);
                imageTracker->activateDataSet(dataSetTarmac);
            }
            else
            {
                imageTracker->deactivateDataSet(dataSetTarmac);
                imageTracker->activateDataSet(dataSetStonesAndChips);
            }
        }
    }
};

ImageTargets_UpdateCallback updateCallback;

JNIEXPORT int JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_getOpenGlEsVersionNative(JNIEnv *, jobject)
{
#ifdef USE_OPENGL_ES_1_1        
    return 1;
#else
    return 2;
#endif
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_setActivityPortraitMode(JNIEnv *, jobject, jboolean isPortrait)
{
    isActivityInPortraitMode = isPortrait;
}



JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_switchDatasetAsap(JNIEnv *, jobject)
{
    switchDataSetAsap = true;
}


JNIEXPORT int JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initTracker(JNIEnv *, jobject)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initTracker");

    // Initialize the image tracker:
    QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
    QCAR::Tracker* tracker = trackerManager.initTracker(QCAR::Tracker::IMAGE_TRACKER);
    if (tracker == NULL)
    {
        LOG("Failed to initialize ImageTracker.");
        return 0;
    }

    LOG("Successfully initialized ImageTracker.");
    return 1;
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_deinitTracker(JNIEnv *, jobject)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_deinitTracker");

    // Deinit the image tracker:
    QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
    trackerManager.deinitTracker(QCAR::Tracker::IMAGE_TRACKER);
}


JNIEXPORT int JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_loadTrackerData(JNIEnv *, jobject)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_loadTrackerData");

    // Get the image tracker:
    QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
    QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>(
                    trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER));
    if (imageTracker == NULL)
    {
        LOG("Failed to load tracking data set because the ImageTracker has not"
            " been initialized.");
        return 0;
    }

    // Create the data sets:
    dataSetStonesAndChips = imageTracker->createDataSet();
    if (dataSetStonesAndChips == 0)
    {
        LOG("Failed to create a new tracking data.");
        return 0;
    }

    dataSetTarmac = imageTracker->createDataSet();
    if (dataSetTarmac == 0)
    {
        LOG("Failed to create a new tracking data.");
        return 0;
    }

    // Load the data sets:
    if (!dataSetStonesAndChips->load("StonesAndChips.xml", QCAR::DataSet::STORAGE_APPRESOURCE))
    {
        LOG("Failed to load data set.");
        return 0;
    }

    if (!dataSetTarmac->load("Tarmac.xml", QCAR::DataSet::STORAGE_APPRESOURCE))
    {
        LOG("Failed to load data set.");
        return 0;
    }

    // Activate the data set:
    if (!imageTracker->activateDataSet(dataSetStonesAndChips))
    {
        LOG("Failed to activate data set.");
        return 0;
    }

    LOG("Successfully loaded and activated data set.");
    return 1;
}


JNIEXPORT int JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_destroyTrackerData(JNIEnv *, jobject)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_destroyTrackerData");

    // Get the image tracker:
    QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
    QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>(
        trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER));
    if (imageTracker == NULL)
    {
        LOG("Failed to destroy the tracking data set because the ImageTracker has not"
            " been initialized.");
        return 0;
    }

    if (dataSetStonesAndChips != 0)
    {
        if (imageTracker->getActiveDataSet() == dataSetStonesAndChips &&
            !imageTracker->deactivateDataSet(dataSetStonesAndChips))
        {
            LOG("Failed to destroy the tracking data set StonesAndChips because the data set "
                "could not be deactivated.");
            return 0;
        }

        if (!imageTracker->destroyDataSet(dataSetStonesAndChips))
        {
            LOG("Failed to destroy the tracking data set StonesAndChips.");
            return 0;
        }

        LOG("Successfully destroyed the data set StonesAndChips.");
        dataSetStonesAndChips = 0;
    }

    if (dataSetTarmac != 0)
    {
        if (imageTracker->getActiveDataSet() == dataSetTarmac &&
            !imageTracker->deactivateDataSet(dataSetTarmac))
        {
            LOG("Failed to destroy the tracking data set Tarmac because the data set "
                "could not be deactivated.");
            return 0;
        }

        if (!imageTracker->destroyDataSet(dataSetTarmac))
        {
            LOG("Failed to destroy the tracking data set Tarmac.");
            return 0;
        }

        LOG("Successfully destroyed the data set Tarmac.");
        dataSetTarmac = 0;
    }

    return 1;
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_onQCARInitializedNative(JNIEnv *, jobject)
{
    // Register the update callback where we handle the data set swap:
    QCAR::registerCallback(&updateCallback);

    // Comment in to enable tracking of up to 2 targets simultaneously and
    // split the work over multiple frames:
    // QCAR::setHint(QCAR::HINT_MAX_SIMULTANEOUS_IMAGE_TARGETS, 2);
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_renderFrame(JNIEnv *, jobject)
{
    //LOG("Java_com_qualcomm_QCARSamples_ImageTargets_GLRenderer_renderFrame");
 
    // Clear color and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    // Get the state from QCAR and mark the beginning of a rendering section
    QCAR::State state = QCAR::Renderer::getInstance().begin();
     
    // Explicitly render the Video Background
    QCAR::Renderer::getInstance().drawVideoBackground();
 
    glEnable(GL_DEPTH_TEST);
 
    // We must detect if background reflection is active and adjust the culling direction.
    // If the reflection is active, this means the post matrix has been reflected as well,
    // therefore standard counter clockwise face culling will result in "inside out" models.
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    if(QCAR::Renderer::getInstance().getVideoBackgroundConfig().mReflection == QCAR::VIDEO_BACKGROUND_REFLECTION_ON)
        glFrontFace(GL_CW);  //Front camera
    else
        glFrontFace(GL_CCW);   //Back camera
 
 
    // Did we find any trackables this frame?
    for(int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
    {
        // Get the trackable:
        const QCAR::TrackableResult* result = state.getTrackableResult(tIdx);
        const QCAR::Trackable& trackable = result->getTrackable();
 
        QCAR::Matrix44F modelViewMatrix =
            QCAR::Tool::convertPose2GLMatrix(result->getPose());
 
 
        // Choose the texture based on the target name:
        int textureIndex;
        if (strcmp(trackable.getName(), "chips") == 0)
        {
            textureIndex = 0;
        }
        else if (strcmp(trackable.getName(), "stones") == 0)
        {
            textureIndex = 1;
        }
        else
        {
            textureIndex = 2;
        }
 
        const Texture* const thisTexture = textures[textureIndex];
 
        QCAR::Matrix44F modelViewProjection;
 
        SampleUtils::translatePoseMatrix(0.0f, 0.0f, kObjectScale,
                                         &modelViewMatrix.data[0]);
        SampleUtils::scalePoseMatrix(kObjectScale, kObjectScale, kObjectScale,
                                     &modelViewMatrix.data[0]);
 
        SampleUtils::multiplyMatrix(&projectionMatrix.data[0],
                                    &modelViewMatrix.data[0] ,
                                    &modelViewProjection.data[0]);
 
        glUseProgram(shaderProgramID);
          
 
        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
                              (const GLvoid*) &bananaVerts[0]);
        glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
                              (const GLvoid*) &bananaNormals[0]);
        glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
                              (const GLvoid*) &bananaTexCoords[0]);
 
         
        glEnableVertexAttribArray(vertexHandle);
        glEnableVertexAttribArray(normalHandle);
        glEnableVertexAttribArray(textureCoordHandle);
         
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
        glUniform1i(texSampler2DHandle, 0);
        glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE,
                           (GLfloat*)&modelViewProjection.data[0] );
 
        glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);
 
        SampleUtils::checkGlError("ImageTargets renderFrame");
    }
 
    glDisable(GL_DEPTH_TEST);
 
    glDisableVertexAttribArray(vertexHandle);
    glDisableVertexAttribArray(normalHandle);
    glDisableVertexAttribArray(textureCoordHandle);
 
    QCAR::Renderer::getInstance().end();
 
}


void
configureVideoBackground()
{
    // Get the default video mode:
    QCAR::CameraDevice& cameraDevice = QCAR::CameraDevice::getInstance();
    QCAR::VideoMode videoMode = cameraDevice.
                                getVideoMode(QCAR::CameraDevice::MODE_DEFAULT);


    // Configure the video background
    QCAR::VideoBackgroundConfig config;
    config.mEnabled = true;
    config.mSynchronous = true;
    config.mPosition.data[0] = 0.0f;
    config.mPosition.data[1] = 0.0f;

    if (isActivityInPortraitMode)
    {
        //LOG("configureVideoBackground PORTRAIT");
        config.mSize.data[0] = videoMode.mHeight
                                * (screenHeight / (float)videoMode.mWidth);
        config.mSize.data[1] = screenHeight;

        if(config.mSize.data[0] < screenWidth)
        {
            LOG("Correcting rendering background size to handle missmatch between screen and video aspect ratios.");
            config.mSize.data[0] = screenWidth;
            config.mSize.data[1] = screenWidth *
                              (videoMode.mWidth / (float)videoMode.mHeight);
        }
    }
    else
    {
        //LOG("configureVideoBackground LANDSCAPE");
        config.mSize.data[0] = screenWidth;
        config.mSize.data[1] = videoMode.mHeight
                            * (screenWidth / (float)videoMode.mWidth);

        if(config.mSize.data[1] < screenHeight)
        {
            LOG("Correcting rendering background size to handle missmatch between screen and video aspect ratios.");
            config.mSize.data[0] = screenHeight
                                * (videoMode.mWidth / (float)videoMode.mHeight);
            config.mSize.data[1] = screenHeight;
        }
    }

    LOG("Configure Video Background : Video (%d,%d), Screen (%d,%d), mSize (%d,%d)", videoMode.mWidth, videoMode.mHeight, screenWidth, screenHeight, config.mSize.data[0], config.mSize.data[1]);

    // Set the config:
    QCAR::Renderer::getInstance().setVideoBackgroundConfig(config);
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative(
                            JNIEnv* env, jobject obj, jint width, jint height)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative");

    // Store screen dimensions
    screenWidth = width;
    screenHeight = height;

    // Handle to the activity class:
    jclass activityClass = env->GetObjectClass(obj);

    jmethodID getTextureCountMethodID = env->GetMethodID(activityClass,
                                                    "getTextureCount", "()I");
    if (getTextureCountMethodID == 0)
    {
        LOG("Function getTextureCount() not found.");
        return;
    }

    textureCount = env->CallIntMethod(obj, getTextureCountMethodID);
    if (!textureCount)
    {
        LOG("getTextureCount() returned zero.");
        return;
    }

    textures = new Texture*[textureCount];

    jmethodID getTextureMethodID = env->GetMethodID(activityClass,
        "getTexture", "(I)Lcom/qualcomm/QCARSamples/ImageTargets/Texture;");

    if (getTextureMethodID == 0)
    {
        LOG("Function getTexture() not found.");
        return;
    }

    // Register the textures
    for (int i = 0; i < textureCount; ++i)
    {

        jobject textureObject = env->CallObjectMethod(obj, getTextureMethodID, i);
        if (textureObject == NULL)
        {
            LOG("GetTexture() returned zero pointer");
            return;
        }

        textures[i] = Texture::create(env, textureObject);
    }
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative finished");
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_deinitApplicationNative(
                                                        JNIEnv* env, jobject obj)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_deinitApplicationNative");

    // Release texture resources
    if (textures != 0)
    {
        for (int i = 0; i < textureCount; ++i)
        {
            delete textures[i];
            textures[i] = NULL;
        }

        delete[]textures;
        textures = NULL;

        textureCount = 0;
    }
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_startCamera(JNIEnv *,
                                                                         jobject)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_startCamera");

    // Select the camera to open, set this to QCAR::CameraDevice::CAMERA_FRONT
    // to activate the front camera instead.
    QCAR::CameraDevice::CAMERA camera = QCAR::CameraDevice::CAMERA_DEFAULT;

    // Initialize the camera:
    if (!QCAR::CameraDevice::getInstance().init(camera))
        return;

    // Configure the video background
    configureVideoBackground();

    // Select the default mode:
    if (!QCAR::CameraDevice::getInstance().selectVideoMode(
                                QCAR::CameraDevice::MODE_DEFAULT))
        return;

    // Start the camera:
    if (!QCAR::CameraDevice::getInstance().start())
        return;

    // Uncomment to enable flash
    //if(QCAR::CameraDevice::getInstance().setFlashTorchMode(true))
    //	LOG("IMAGE TARGETS : enabled torch");

    // Uncomment to enable infinity focus mode, or any other supported focus mode
    // See CameraDevice.h for supported focus modes
    //if(QCAR::CameraDevice::getInstance().setFocusMode(QCAR::CameraDevice::FOCUS_MODE_INFINITY))
    //	LOG("IMAGE TARGETS : enabled infinity focus");

    // Start the tracker:
    QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
    QCAR::Tracker* imageTracker = trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER);
    if(imageTracker != 0)
        imageTracker->start();
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_stopCamera(JNIEnv *, jobject)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_stopCamera");

    // Stop the tracker:
    QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
    QCAR::Tracker* imageTracker = trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER);
    if(imageTracker != 0)
        imageTracker->stop();

    QCAR::CameraDevice::getInstance().stop();
    QCAR::CameraDevice::getInstance().deinit();
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_setProjectionMatrix(JNIEnv *, jobject)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_setProjectionMatrix");

    // Cache the projection matrix:
    const QCAR::CameraCalibration& cameraCalibration =
                                QCAR::CameraDevice::getInstance().getCameraCalibration();
    projectionMatrix = QCAR::Tool::getProjectionGL(cameraCalibration, 2.0f, 2500.0f);
}

// ----------------------------------------------------------------------------
// Activates Camera Flash
// ----------------------------------------------------------------------------
JNIEXPORT jboolean JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_activateFlash(JNIEnv*, jobject, jboolean flash)
{
    return QCAR::CameraDevice::getInstance().setFlashTorchMode((flash==JNI_TRUE)) ? JNI_TRUE : JNI_FALSE;
}

JNIEXPORT jboolean JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_autofocus(JNIEnv*, jobject)
{
    return QCAR::CameraDevice::getInstance().setFocusMode(QCAR::CameraDevice::FOCUS_MODE_TRIGGERAUTO) ? JNI_TRUE : JNI_FALSE;
}


JNIEXPORT jboolean JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_setFocusMode(JNIEnv*, jobject, jint mode)
{
    int qcarFocusMode;

    switch ((int)mode)
    {
        case 0:
            qcarFocusMode = QCAR::CameraDevice::FOCUS_MODE_NORMAL;
            break;

        case 1:
            qcarFocusMode = QCAR::CameraDevice::FOCUS_MODE_CONTINUOUSAUTO;
            break;

        case 2:
            qcarFocusMode = QCAR::CameraDevice::FOCUS_MODE_INFINITY;
            break;

        case 3:
            qcarFocusMode = QCAR::CameraDevice::FOCUS_MODE_MACRO;
            break;

        default:
            return JNI_FALSE;
    }

    return QCAR::CameraDevice::getInstance().setFocusMode(qcarFocusMode) ? JNI_TRUE : JNI_FALSE;
}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_initRendering(
                                                    JNIEnv* env, jobject obj)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_initRendering");

    // Define clear color
    glClearColor(0.0f, 0.0f, 0.0f, QCAR::requiresAlpha() ? 0.0f : 1.0f);

    // Now generate the OpenGL texture objects and add settings
    for (int i = 0; i < textureCount; ++i)
    {
        glGenTextures(1, &(textures[i]->mTextureID));
        glBindTexture(GL_TEXTURE_2D, textures[i]->mTextureID);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textures[i]->mWidth,
                textures[i]->mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                (GLvoid*)  textures[i]->mData);
    }
#ifndef USE_OPENGL_ES_1_1

    shaderProgramID     = SampleUtils::createProgramFromBuffer(cubeMeshVertexShader,
                                                            cubeFragmentShader);

    vertexHandle        = glGetAttribLocation(shaderProgramID,
                                                "vertexPosition");
    normalHandle        = glGetAttribLocation(shaderProgramID,
                                                "vertexNormal");
    textureCoordHandle  = glGetAttribLocation(shaderProgramID,
                                                "vertexTexCoord");
    mvpMatrixHandle     = glGetUniformLocation(shaderProgramID,
                                                "modelViewProjectionMatrix");
    texSampler2DHandle  = glGetUniformLocation(shaderProgramID,
                                                "texSampler2D");

#endif

}


JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_updateRendering(
                        JNIEnv* env, jobject obj, jint width, jint height)
{
    LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_updateRendering");

    // Update screen dimensions
    screenWidth = width;
    screenHeight = height;

    // Reconfigure the video background
    configureVideoBackground();
}


#ifdef __cplusplus
}
#endif

 

 

Convert .obj to .h

March 13, 2013 - 6:54pm #20

Thanks AlessandroB,

I'm changed model 3D in sample Image Target

Convert .obj to .h

March 13, 2013 - 11:31pm #19

You're welcome

Convert .obj to .h

April 8, 2013 - 4:24am #18

 

Hi i follow this  banana tutorial i change the code but i can buil ndk-build i have some errors.

I think i have to changed model 3D in sample Image target like the previous post.

But i don't know how make that or were we cand make the command.

Where is the obj2opengl.pl directory.

Thanks!!!

 

Convert .obj to .h

April 8, 2013 - 6:34am #17

Hi, you need first to generate the banana.h file and add it to your JNI folder under your project directory.

The full tutorial with all the steps, code snippets and links to the obj2opengl script is here:

https://developer.vuforia.com/resources/dev-guide/replacing-teapot

 

Convert .obj to .h problem

April 19, 2013 - 1:25am #16

Good day, i face some problem on converting .obj file into .h file. when i enter "obj2opengl.pl xxx.obj" in my CMD....the output as attachment below prompt out and the .h file is not create.....can someone help me solving this? Thanks :)

AttachmentSize
Image icon error 2.JPG68.02 KB

Convert .obj to .h

April 19, 2013 - 1:59am #15

Hi, firstly you must put your .obj file and obj2opengl.pl script in the same folder. after that in cmd screen you must write command like this:

"perl obj2opengl.pl yourobjectname.obj"

Good day...

Convert .obj to .h

May 5, 2013 - 5:52pm #14

My problem was the value of kObjectScale variable.

Now it is resolved, so, a banana is the new Main Stream of this fórum...

Thank's guys

Convert .obj to .h

May 6, 2013 - 6:23pm #13

Hi , @AlessandroB,

tutorial here https://developer.vuforia.com/resources/dev-guide/replacing-teapot is for OpenGl 2.0

What is different with OpenGl 1.1 or where i can find that tutorial for OpenGl 1.1

*My android device is 4.0.4 version, but not support OpenGl 2.0.

Convert .obj to .h

May 7, 2013 - 12:19am #12

Hi mobiro, you can follow the same tutorial also for OpenGL 1.1; the only difference is that you need to put your vertex arrays into these lines:

 

 
 glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) &teapotTexCoords[0]);
 glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &teapotVertices[0]);
 glNormalPointer(GL_FLOAT, 0,  (const GLvoid*) &teapotNormals[0]);

 

 
(Instead of the glVertexAttrib ( ... ) functions which are specific to GL ES 2.0); so, baically you need to replace the teapottexCoords, teapotVertices and teapotNormals with the vertex arrays of your object.
 
Note: you find those three lines already in the code of ImageTargets sample.
 
The, as explained in the tutorial for 2.0, you need to use glDrawArrays (and remove glDrawElements()).
 
Also, to run on 1.1, make sure to have the right setting in the Android.mk file:
 
USE_OPENGL_ES_1_1 := true

Convert .obj to .h

May 8, 2013 - 11:46am #11

@AlessandroB, I try to replace teapot with banana.  I try to follow your explanation in this thread, https://developer.vuforia.com/resources/dev-guide/replacing-teapot, and https://developer.vuforia.com/forum/faq/android-how-do-i-replace-teapot.

yeah, I can remove teapot object and show banana object.
But, the Banana show in 2-D and white(no color/texture).

any step i miss?

Convert .obj to .h

May 8, 2013 - 11:53am #10

Hi,

this is probably because you are using GL 1.1 and maybe did not enable texture mapping;

can you check that you have this code:

glEnable(GL_TEXTURE_2D);

 

glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
 
and also this (before calling glVertex....)
 
 glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
        
More in general, check the implementation of the official ImageTargets sample, to make sure that you are using all the necessary OpenGL 1.1-specific code (and not the GL 2.0 code)
 

Convert .obj to .h

May 8, 2013 - 6:23pm #9

Yes, I have that code..

and I think I use all the necessary OpenGL 1.1-specific, code cause no code i erase/remove in sample app.

by the way, ImageTargets sample app use OpenGl 1.1 right?
and it running well with it's texture/color on my device.

Convert .obj to .h

May 9, 2013 - 12:05am #8

Hi, ImageTargets use 2.0 by default; to make it work with 1.1 you need to specify the USE_OPENGL_ES_11 flag (set it to true) in the Android.mk file;

if you did not do that, and the sample shows the teapot, it would mean that your device supports GL ES 2.0 !!

Then it would also mean you could implement the tutorial code changes for 2.0

Convert .obj to .h

May 9, 2013 - 1:33am #7

Hi @AlessandroB,

I think I ask with wrong question.. I'm sorry..

What I mean is I can run ImageTargets Sample app in my device very well with texture/color (if I set USE_OPENGL_ES_1_1 to true)

so, I think GL 1.1 is not a problem in my banana case.

Maybe any other setting that I miss.. But I can't find that yet.

*this post have relation with my other here https://developer.vuforia.com/forum/qcar-api/imagetargets-sample-show-dark-screen

regards.

Convert .obj to .h

May 9, 2013 - 11:44am #6

I see. So, GLES 1.1 is all right, but you see a white / untextured model.

Have you put the banana texture in the assets folder of your project and adjusted the code in loadTextures() in ImageTargets.java so to load the banana texture (instead of loading the teapot textures) ?

 

Convert .obj to .h

May 9, 2013 - 3:35pm #5

yes, I put the banana texture in the assets folder and adjusted the code in loadTextures() in ImageTargets.java.

it's still not working at the first trial ...

then i set kObjectScale to 100.0f, it's still without color.

and it works when kObjectScale set to 120.f  :)

Problem solve.

Thanks AlessandroB

Convert .obj to .h

May 10, 2013 - 6:53am #4

Hi, ok, that sounds very weird (i;e. tetures showing up when ObjectScale is 120...), ;-)

however I'm glad to hear it is solved !

Convert .obj to .h

May 10, 2013 - 8:07pm #3

I don't know if that is weird.

I just follow what @Werther said at here :

https://developer.vuforia.com/forum/android/replace-3d-model-different-3d-model#comment-2013271

under @DavidBread advise,,, :)

Convert .obj to .h

May 11, 2013 - 2:09am #2

Ok, thanks for the pointer to the thread.

Convert .obj to .h

May 18, 2019 - 5:56am #1

link is broken

kindly help

Log in or register to post comments