Error when outputting the earth obj in OpenGl - c++

I want to print out the earth obj, but it keeps printing strangely like a picture.
The vertexes are printed in an empty form in the middle.
_mesh = new Mesh("obj\\13902_Earth_v1_l3.obj", "obj\\Earth_diff.jpg");
First, enter the file name like this. Over there, _mesh is the object of the Mesh class that I created.
Mesh(char* obj, char* texture) {
open(obj);
loadTexture(texture, _textureIndex);
}
This is the constructor of the Mesh class. The Opne function outputs obj, and loadTexture reads the texture. just look at the Open function.
void Mesh::open(char* file)
{
FILE* fp;
char buffer[100] = { 0 };
Vec3<double> pos;
int index[3], tex[3], empty[3];
int id = 0;
_minBound.Set(1000000.0);
_maxBound.Set(-1000000.0);
fopen_s(&fp, file, "r");
while (fscanf(fp, "%s %lf %lf %lf", buffer, &pos[0], &pos[1], &pos[2]) != EOF)
{
// v 0.2 0.3 0.1
// vt
if (buffer[0] == 'v' && buffer[1] == NULL) {
for (int i = 0; i < 3; i++) {
if (_minBound[i] > pos[i]) _minBound[i] = pos[i];
if (_maxBound[i] < pos[i]) _maxBound[i] = pos[i];
}
_vertices.push_back(new Vertex(id, pos));
}
}
// read texture coordinate of vertics
id = 0;
fseek(fp, 0, SEEK_SET);
while (fscanf(fp, "%s %lf %lf", &buffer, &pos[0], &pos[1]) != EOF) {
if (!strcmp(buffer, "vt")) {
_textureCoords.push_back(new Texture(pos[0], 1.0 - pos[1], 0.0));
}
}
// read faces
id = 0;
fseek(fp, 0, SEEK_SET);
while (fscanf(fp, "%s %d/%d/%d %d/%d/%d %d/%d/%d", &buffer, &index[0], &tex[0], &empty[0], &index[1], &tex[1], &empty[1], &index[2], &tex[2], &empty[2]) != EOF) {
if (buffer[0] == 'f' && buffer[1] == NULL) {
auto v0 = _vertices[index[0] - 1];
auto v1 = _vertices[index[1] - 1];
auto v2 = _vertices[index[2] - 1];
_faces.push_back(new Face(id++, v0, v1, v2, tex[0] - 1, tex[1] - 1, tex[2] - 1));
//_faces.push_back(new Face(index++, _vertices[v_index[0] - 1], _vertices[v_index[1] - 1], _vertices[v_index[2] - 1]));
}
}
fclose(fp);
moveToCenter(10.0);
makeList();
computeNormal();
}
In the code, _vertices and _faces are class vectors that I've created. It's simply a text file in this format that's made vector computation.
And I didn't read the value of vn there, and I didn't read the third value of f. Then at least the vertex value would have been entered well, but why does it print out like that?
This is what it looks like when I don't put on textures.
All other sphere objects are printed in that form. How do we solve this?

Related

Unable to use jstring as an argument inside native code

I need to use const char * inside my native code so , I took the argument from java side as jstring and use the following statements
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;
}
this function says unable to read mtl file whose code is in glm.c..a part of it is below ...have a look at ReadOBJ and ReadMTL functions
#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;
}
However , the following snippet works
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");
}
The only difference seem to be , that in intialize , I have hardcoded the paths ....but in addMarkerandModel ...I am giving them as parameters passed through jni
Please help!!!!
Reading a .obj file in ARToolKit's glm proceeds in a few steps. First, the .obj file is parsed, then any referenced .mtl files are loaded, and finally, if the .mtl file refers to a texture (only power-of-two size .sgi and JPEGs are supported in ARToolKit's glm reader) then those are lazily loaded once an OpenGL context is available.
If you're getting an error that the .mtl file can't be found, then it indicates that the first step is actually OK. glm was able to find and read the .obj file, but the .obj file referred to a .mtl file which couldn't be found.
Go through your .obj file(s) in a text editor, find all .mtl references, and edit them so that the correct relative path is referred to.
I would suggest to work with supper simple code first. Try to isolate the issue. Make sure that passed string is actually what you are looking for.
Here: http://jnicookbook.owsiak.org/recipe-No-009/
you can find supper simple sample code. Just the raw string processing.
Try to start with similar code in your case. Check whether passed value is really what you are looking for.

how to fill the "data field" of wavfile

Hi i am trying to record from a board and i have successfully record 4 seconds. Problem is when i try to record for more time, i got an error telling me that there not enough memory. my target is to record a 5 minutes file. Until now i have create a buffer named snIn[256] where are the samples. i send it to a big buffer of [16K * 4sec] and when it is full, i create the wav file.
#include "SAI_InOut.hpp"
#include "F746_GUI.hpp"
#include "Delay.hpp"
#include "WaveformDisplay.hpp"
#include "SDFileSystem.h"
#include "wavfile.h"
using namespace Mikami;
#define RES_STR_SIZE 0x20
#define WAVFILE_SAMPLES_PER_SECOND 16000
#define REC_TIME 4
//Create an SDFileSystem object
SDFileSystem sd("sd");
bool flag = 1;
int count = 0;
char *res_buf;
int rp = 0;
const int NUM_SAMPLES = WAVFILE_SAMPLES_PER_SECOND * REC_TIME;
Array<int16_t> my_buffer(NUM_SAMPLES);
int j = 0;
static const char *target_filename = "/sd/rectest.wav";
const int SEG_SIZE = 256;
int sent_array = 0;
int rec(const char *filename, Array<int16_t> my_buffer)
{
j = 0;
flag = 0;
sent_array = 0;
WavFileResult result;
wavfile_info_t info;
wavfile_data_t data;
WAVFILE_INFO_AUDIO_FORMAT(&info) = 1;
WAVFILE_INFO_NUM_CHANNELS(&info) = 1;
WAVFILE_INFO_SAMPLE_RATE(&info) = WAVFILE_SAMPLES_PER_SECOND;
WAVFILE_INFO_BITS_PER_SAMPLE(&info) = 16;
WAVFILE_INFO_BYTE_RATE(&info) = WAVFILE_INFO_NUM_CHANNELS(&info) * WAVFILE_INFO_SAMPLE_RATE(&info) * (WAVFILE_INFO_BITS_PER_SAMPLE(&info) / 8);
WAVFILE_INFO_BLOCK_ALIGN(&info) = 2;
WAVFILE *wf = wavfile_open(filename, WavFileModeWrite, &result);
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf, RES_STR_SIZE);
printf("%s", res_buf);
return result;
} else printf ("Open file success \r\n");
rp = 0;
WAVFILE_DATA_NUM_CHANNELS(&data) = 1;
result = wavfile_write_info(wf, &info);
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf, RES_STR_SIZE);
printf("%s", res_buf);
return result; } else printf ("Write info success \r\n");
while ( rp < NUM_SAMPLES ) {
WAVFILE_DATA_CHANNEL_DATA(&data, 0) = my_buffer[rp];
result = wavfile_write_data(wf, &data);
rp += 1;
}
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf, RES_STR_SIZE);
printf("%s", res_buf);
return result; } else printf ("Write Data file success \r\n");
result = wavfile_close(wf);
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf , RES_STR_SIZE);
printf("%s", res_buf);
return result; } else printf ("Close file success \r\n");
//UnMount the filesystem
sd.unmount();
printf("Success rec !\r\n");
return 0;
}
int main()
{
//Mount the filesystem
sd.mount();
const float MAX_DELAY = 0.5f; // 最大遅延,単位:秒
const int FS = I2S_AUDIOFREQ_16K; // 標本化周波数: 16 kHz
const uint32_t MAX_ARRAY_SIZE = (uint32_t)(MAX_DELAY*FS);
SaiIO mySai(SaiIO::BOTH, 256, FS, INPUT_DEVICE_DIGITAL_MICROPHONE_2);
Label myLabel(185, 10, "Delay System", Label::CENTER, Font16);
// ButtonGroup: "ON", "OFF"
const uint16_t BG_LEFT = 370;
const uint16_t BG_WIDTH = 100;
const uint16_t BG_HEIGHT = 45;
ButtonGroup onOff(BG_LEFT, 40, BG_WIDTH/2, BG_HEIGHT,
2, (string[]){"ON", "OFF"}, 0, 0, 2, 1);
const uint16_t SB_LEFT = BG_LEFT - 320;
const uint16_t SB_WIDTH = 270;
const uint16_t SB_Y0 = 240;
char str[20];
sprintf(str, " %3.1f [s]", MAX_DELAY);
SeekBar barDelay(SB_LEFT, SB_Y0, SB_WIDTH,
0, MAX_ARRAY_SIZE, 0, "0", "", str);
NumericLabel<float> labelDelay(SB_LEFT+SB_WIDTH/2, SB_Y0-40, "DELEY: %4.2f", 0, Label::CENTER);
DelaySystem delaySystem(MAX_ARRAY_SIZE);
WaveformDisplay displayIn(*GuiBase::GetLcdPtr(), SB_LEFT+7, 70, 256, 9,LCD_COLOR_WHITE, LCD_COLOR_CYAN,GuiBase::ENUM_BACK);
Label inLabel(SB_LEFT-30, 65, "IN");
WaveformDisplay displayOut(*GuiBase::GetLcdPtr(), SB_LEFT+7, 130, 256, 9,LCD_COLOR_WHITE, LCD_COLOR_CYAN,GuiBase::ENUM_BACK);
Label outLabel(SB_LEFT-30, 125, "OUT");
int runStop = 1;
Array<int16_t> snIn(mySai.GetLength());
Array<int16_t> snOut(mySai.GetLength());
mySai.RecordIn();
mySai.PlayOut();
mySai.PauseOut();
while (true)
{
// On/OFF
int num;
if (onOff.GetTouchedNumber(num))
if (runStop != num)
{
if (num == 0) mySai.ResumeOut();
else mySai.PauseOut();
runStop = num;
}
if (mySai.IsCompleted())
{
for (int n=0; n<mySai.GetLength() ; n++)
{
int16_t xL, xR;
mySai.Input(xL,xR);
int16_t xn = xL + xR;
snIn[n] = xn;
my_buffer[j] = xn;
j++;
if (j == NUM_SAMPLES && flag == 1) {
rec (target_filename , my_buffer); }
int16_t yn = delaySystem.Execute(xn);
mySai.Output(yn, yn);
snOut[n] = yn;
}
mySai.Reset();
displayIn.Execute(snIn);
}
}
}
I thought about a possible solution, to fill directly the "data field" of the wavefile with the snIn[256] buffer (instead of using my_buffer) again and again and at the end close the wavfile. Please let me know what you think about that and other solutions
things to note: 1) while a write operation is being performed, more data is still coming in.
At the very least I would double buffer that data, so can be writing one buffer while the other one fills.
Usually this means using an interrupt to collect the samples (into which ever buffer is currently being filed.)
the foreground program waits for the current buffer to be 'full', then initiates write operation.,
then waits again for a buffer to be 'full'
The interrupt function tracks which buffer is being filled and the current index into that buffer. When a buffer is full, set a 'global' status to let the foreground program know which buffer is ready to be written.
The foreground program writes the buffer, then resets the status for that buffer.

Some Triangles not displaying when trying to draw a mesh from a .obj in OpenGL

I'm attempting to display an object loaded from a .obj file. I use this function to read in the .obj:
bool loadOBJ(
const char * path,
std::vector<glm::vec3> & vertices,
std::vector<glm::vec3> & vertexIndices
){
printf("Loading OBJ file %s...\n", path);
FILE * file = fopen(path, "r");
if( file == NULL ){
printf("Impossible to open the file ! Are you in the right path ? \n");
getchar();
return false;
}
while( 1 ){
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
// else : parse lineHeader
if ( strcmp( lineHeader, "v" ) == 0 ){
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z );
vertices.push_back(vertex);
}else if ( strcmp( lineHeader, "f" ) == 0 ){
glm::vec3 vertexIndex;
fscanf(file, "%f %f %f\n", &vertexIndex.x, &vertexIndex.y, &vertexIndex.z );
vertexIndices.push_back(vertexIndex);
}else{
// Probably a comment, eat up the rest of the line
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
}
}
return true;
}
I then call this function in my init function.
Once the mesh is loaded I display it by looping through the vertices here:
for (unsigned int i = 0; i < meshVertices.size(); i++)
{
glBegin(GL_TRIANGLES);
glVertex3f(meshVertices[faceIndices[i].x-1].x, meshVertices[faceIndices[i].x-1].y, meshVertices[faceIndices[i].x-1].z);
glVertex3f(meshVertices[faceIndices[i].y-1].x, meshVertices[faceIndices[i].y-1].y, meshVertices[faceIndices[i].y-1].z);
glVertex3f(meshVertices[faceIndices[i].z-1].x, meshVertices[faceIndices[i].z-1].y, meshVertices[faceIndices[i].z-1].z);
glEnd();
}
However, when the program runs, the far side of the object doesn't load at all and random triangles are missing. Like this:
You don't want to loop the size of the vertices, but the size of the faces.
Your loop should read for (unsigned int i = 0; i < faceIndices.size(); i++)
You are looping through the variable faceIndices[i] and I suppose that you want to draw all the triangles, not all the point (vertices)!
On a side note: Am I teaching you this course? :D
That code looks familiar...

Color switching of an image using C++ code

Since i am quiet new to C++ and Image processing i have a problem modifying and adding a function to the code.
The requirement is only to switch between the RGB colors.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "math.h"
class myImageData
{
private:
int mW;
int mH;
int mCH;
double * mData;
void SkipComments(FILE *fp)
{
int ch;
char line[100];
while ((ch = fgetc(fp)) != EOF && isspace(ch))
;
if (ch == '#')
{
fgets(line, sizeof(line), fp);
SkipComments(fp);
}
else
{
fseek(fp, -1, SEEK_CUR);
}
}
public:
myImageData(void)
{
this->mData = NULL;
}
~myImageData()
{
if (this->mData != NULL)
{
delete[] this->mData;
}
}
void init(int W, int H, int CH)
{
this->mW = W;
this->mH = H;
this->mCH = CH;
if (this->mData != NULL)
delete[] this->mData;
this->mData = new double[(this->mW)*(this->mH)*(this->mCH)];
}
int getWidth(void)
{
return this->mW;
}
int getHeight(void)
{
return this->mH;
}
int getCH(void)
{
return this->mCH;
}
double * getDataPtr(void)
{
return this->mData;
}
double get(int x, int y)
{
return this->mData[y*(this->mW) + x];
}
double get(int x, int y, int CH)
{
return this->mData[this->mCH * (y*(this->mW) + x) + CH];
}
void set(int x, int y, double value)
{
this->mData[y*(this->mW) + x] = value;
}
void set(int x, int y, int CH, double value)
{
this->mData[this->mCH *(y*(this->mW) + x) + CH] = value;
}
void read(const char *filename);
void save(const char *filename);
};
void myImageData::read(const char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL){
printf("Cannot open %s\n", filename);
exit(1); //abnormal termination
}
printf("Read an image from: %s\n", filename);
// read ppm/pgm header
char buf[256];
char filetype[256];
int W, H, Range, CH;
fgets(buf, sizeof(buf), file);
sscanf(buf, "%s", filetype);
SkipComments(file);
fgets(buf, sizeof(buf), file);
sscanf(buf, "%d%d", &W, &H);
SkipComments(file);
fgets(buf, sizeof(buf), file);
sscanf(buf, "%d", &Range);
//printf("Header: %s, %d, %d, %d\n", filetype, W, H, Range);
SkipComments(file);
if (strcmp(filetype, "P5") == 0)
{
CH = 1;
}
else if (strcmp(filetype, "P6") == 0)
{
CH = 3;
}
else
{
printf("Unknown image type\n");
exit(1); //abnormal termination
}
if (Range != 255){
printf("Invalid data\n");
exit(1); //abnormal termination
}
// create myImageData class
init(W, H, CH);
// read ppm data
int datalength = this->mW * this->mH * this->mCH;
unsigned char * temp = new unsigned char[datalength];
fread(temp, sizeof(unsigned char), datalength, file);
double * ptr1 = this->mData;
unsigned char *ptr2 = temp;
for (int i = 0; i < datalength; i++){
*ptr1 = (double)*ptr2;
ptr1++;
ptr2++;
}
delete[] temp;
fclose(file);
}
void myImageData::save(const char *filename){
char filenamefull[256];
if (this->mCH == 1){
sprintf(filenamefull, "%s.pgm", filename);
}
else{
sprintf(filenamefull, "%s.ppm", filename);
}
FILE *file = fopen(filenamefull, "w");
printf("Write an image to: %s \n", filenamefull);
if (this->mCH == 1){
fprintf(file, "P5\n");
}
else{
fprintf(file, "P6\n");
}
fprintf(file, "%d %d\n", this->mW, this->mH);
fprintf(file, "255\n");
int datalength = this->mW * this->mH * this->mCH;
unsigned char * temp = new unsigned char[datalength];
double * ptr1 = this->mData;
unsigned char * ptr2 = temp;
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
fwrite(temp, sizeof(unsigned char), datalength, file);
delete[] temp;
fprintf(file, "Â¥n");
fclose(file);
}
The errors i am having:
error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
error LNK1120: 1 unresolved externals
Firstly, you have no main function. No surprise that your code doesn't work.. all you have is a class to load, save and manipulate PPM image files.
You appear to me using Visual Studio, so you'll need a function that looks like this:
int _tmain(int argc, _TCHAR* argv[])
{
myImageData image;
image.read("atestfile.ppm");
// do some stuff to your image
image.write("outputfile.ppm");
}
I'm assuming you have a test image in PPM format you can use here, of course.
Now this is madness:
double * ptr1 = this->mData;
unsigned char * ptr2 = temp;
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
You've read from an unsigned char, so there's no point stuffing it into a double, and there's definitely no point in checking if the value lies outside of 0 to 255. Why are you storing things in doubles? It makes no sense! Even if you did do something that needed a full double-precision floating point value per channel, you throw it all away in the output when you clamp everything to 0-255 again:
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
Also, this is basically C dressed up in a thin C++ veneer. That's okay, everyone has to start somewhere. But instead of using new to create an array, you can do this:
// read ppm data
int datalength = this->mW * this->mH * this->mCH;
// using a std::vector here means that the allocated memory will be freed
// automatically, even in the result of an error occurring.
std::vector<unsigned char> temp(datalength);
fread(&temp[0], sizeof(unsigned char), datalength, file);
I'd also consider using iostream classes such as fstream instead of fread and fopen and so on. But this is not really the place to get into those kinds of details.
Anyway, What to do with your image once it is loaded? You've got dead easy helper functions to read and write pixel values, which will let you do pretty much anything you want. Here's a simple example, swapping the R and B channels. You might get something better when you actually tell us what you wanted.
void swapRB(myImageData& image)
{
assert(image.getCH() == 3);
for (int x = 0; x < image.getWidth())
{
for (int y = 0; x < image.getHeight())
{
double R = image.get(x, y, 0);
double G = image.get(x, y, 1);
double B = image.get(x, y, 2);
image.set(x, y, 0, B);
image.set(x, y, 2, R);
}
}
}

Rendering .obj files with OpenGL

I have been having problems rendering a model in opengl. I have made my own obj parser and a render function using glDrawElements but I can't see the problem. This is my parser function:
void load_obj(char *nom)
{
FILE *file = fopen(nom, "r");
int iv = 0, in = 0, it = 0, ifa = 0;
if(file != NULL)
{
while(1)
{
char lineHeader[128];
int res = fscanf(file, "%s", lineHeader);
if(res == EOF)
break;
if(strcmp(lineHeader, "v") == 0)
{
float vertex[3] = {0,0,0};
fscanf(file, "%f %f %f\n",
&vertex[0], &vertex[1], &vertex[2]);
vertices[iv] = vertex[0];
vertices[iv+1] = vertex[1];
vertices[iv+2] = vertex[2];
iv += 3;
}
else if(strcmp(lineHeader, "vt") == 0)
{
float tex_vert[2] = {0,0};
fscanf(file, "%f %f\n",
&tex_vert[0], &tex_vert[1]);
texturas[it] = tex_vert[0];
texturas[it+1] = tex_vert[1];
it += 2;
}
else if(strcmp(lineHeader, "vn") == 0)
{
float normal[3] = {0,0,0};
fscanf(file, "%f %f %f\n",
&normal[0], &normal[1], &normal[2]);
normales[in] = normal[0];
normales[in+1] = normal[1];
normales[in+2] = normal[2];
in += 3;
}
else if(strcmp(lineHeader, "f") == 0)
{
unsigned int vertexIndex[9] = {0,0,0,0,0,0,0,0,0};
fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
&vertexIndex[0], &vertexIndex[1], &vertexIndex[2],
&vertexIndex[3], &vertexIndex[4], &vertexIndex[5],
&vertexIndex[6], &vertexIndex[7], &vertexIndex[8]);
vertTriangulos[ifa] = vertexIndex[0];
vertTriangulos[ifa+1] = vertexIndex[1];
vertTriangulos[ifa+2] = vertexIndex[2];
vertTriangulos[ifa+3] = vertexIndex[3];
vertTriangulos[ifa+4] = vertexIndex[4];
vertTriangulos[ifa+5] = vertexIndex[5];
vertTriangulos[ifa+6] = vertexIndex[6];
vertTriangulos[ifa+7] = vertexIndex[7];
vertTriangulos[ifa+8] = vertexIndex[8];
ifa += 9;
nTriangulos++;
}
}
}
And this is my draw function:
void draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texturas);
glNormalPointer(GL_FLOAT, 0, normales);
glDrawElements(GL_TRIANGLES, nTriangulos*9, GL_UNSIGNED_INT, vertTriangulos);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
Being the variables:
long nTriangulos;
float *vertices, *normales, *texturas;
unsigned int *vertTriangulos;
The obj file I'm using is a simple cube, but the mesh I'm rendering is a complete disaster.
EDIT:
I have changed my code and now the parser looks like this:
if(strcmp(lineHeader, "f") == 0)
{
unsigned int vertexIndex[9] = {0,0,0,0,0,0,0,0,0};
fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
&vertexIndex[0], &vertexIndex[1], &vertexIndex[2],
&vertexIndex[3], &vertexIndex[4], &vertexIndex[5],
&vertexIndex[6], &vertexIndex[7], &vertexIndex[8]);
for(int i = 0; i < 9; i += 3)
{
bool cierto = true;
int pos = 0;
if(indexbuff.size() > 0)
{
for(int i = 0; i < registro.size(); i++)
{
if(vertexIndex[0] == registro[i].in1
&& vertexIndex[1] == registro[i].in2
&& vertexIndex[2] == registro[i].in3)
{
cierto = false;
pos = i;
}
}
}
if(cierto)
{
verticebuff.push_back(vertices[vertexIndex[i]]);
verticebuff.push_back(vertices[vertexIndex[i]+1]);
verticebuff.push_back(vertices[vertexIndex[i]+2]);
textbuff.push_back(texturas[vertexIndex[i+1]]);
textbuff.push_back(texturas[vertexIndex[i+1]+1]);
normalbuff.push_back(normales[vertexIndex[i+2]]);
normalbuff.push_back(normales[vertexIndex[i+2]+1]);
normalbuff.push_back(normales[vertexIndex[i+2]+2]);
indexbuff.push_back(verticebuff.size()/3);
index3 indice;
indice.in1 = vertexIndex[i];
indice.in2 = vertexIndex[i+1];
indice.in3 = vertexIndex[i+2];
registro.push_back(indice);
}
else
{
indexbuff.push_back(i);
}
}
}
But it doesn't seem to work properly.
Classic obj to opengl buffer mistake, the element buffer index points to all attributes. In other words if opengl sees a 0 index it takes the first element out of all the enabled buffers and move on to the next index. There is no way to use the obj structure directly without duplication of the data as you are reading
you face code should be
if(/*vertexIndex[0..2] triplet has not been seen yet*/){
verticebuff.pushback(vertices[vertexIndex[0]]);
verticebuff.pushback(vertices[vertexIndex[0]+1]);
verticebuff.pushback(vertices[vertexIndex[0]+2]);
textbuff.pushback(texturas[vertexIndex[1]]);
textbuff.pushback(texturas[vertexIndex[1]+1]);
normalbuff.pushback(normales[vertexIndex[2]]);
normalbuff.pushback(normales[vertexIndex[2]+1]);
indexbuff.pushback(verticebuff.size()/3);
} else {
indexbuff.pushback(/*index of the seen triplet*/);
}
//repeat 3 times
then you can paint them with draw elements.