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.
Related
So I am trying to use libpng to write png's from an array of unsigned char that are a bit depth of 1. Meaning for all bits, there is only black and white, as a gray scale image. I have managed to do this successfully for 8-bit depth gray scale png, but not 1 bit depth. Here is the code i have :
extern int write_png_bwsq(const char* filename,
int dimen,
const unsigned char *buffer,
char* title)
{
int yrow;
int dim_bytes;
int code = 1;
FILE *fp = NULL;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_bytep row = NULL;
dim_bytes = (dimen * dimen) / 8;
// Open file for writing (binary mode)
fp = fopen(filename, "wb");
if (fp == NULL) {
fprintf(stderr, "PNG ERROR: Could not open file %s for writing\n", filename);
code = 0;
goto finalise;
}
// Initialize write structure
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fprintf(stderr, "PNG ERROR: Could not allocate PNG write struct\n");
code = 0;
goto finalise;
}
// Initialize info structure
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fprintf(stderr, "PNG ERROR: Could not allocate PNG info struct\n");
code = 0;
goto finalise;
}
// Setup Exception handling
if (setjmp(png_jmpbuf(png_ptr))) {
fprintf(stderr, "PNG Error: Creating the PNG output failed.\n");
code = 0;
goto finalise;
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, dimen, dimen,
1, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
// Sets the title
if (title != NULL) {
png_text title_text;
title_text.compression = PNG_TEXT_COMPRESSION_NONE;
title_text.key = "Title";
title_text.text = title;
png_set_text(png_ptr, info_ptr, &title_text, 1);
}
png_write_info(png_ptr, info_ptr);
row = (png_bytep) buffer;
// Write image data
for (yrow=0 ; yrow<dim_bytes ; yrow++) {
png_write_row(png_ptr, row);
++row;
}
// End write operation
png_write_end(png_ptr, NULL);
finalise:
if (fp != NULL) fclose(fp);
if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return code;
}
Then, i have a separate file where i prepare my image
#include "write_pngs.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#if CHAR_BIT != 8
# error "CHAR_BIT is not usable on this platform"
#endif
#define PIC_SIZE_DIM 1080
#define PIC_SIZE_BW ((PIC_SIZE_DIM * PIC_SIZE_DIM) / CHAR_BIT)
static unsigned char PIC_BITS[PIC_SIZE_BW] = {0};
static void __write_bits_pic(void)
{
size_t i = 1000;
for(;i < 140000;++i) {
PIC_BITS[i] = ((i + 76) >> 5) & 0xff;
}
}
int main(void) {
__write_bits_pic();
printf("Writing picture of %d bytes and %d bits\n", PIC_SIZE_BW, PIC_SIZE_BW * CHAR_BIT);
return !write_png_bwsq("bwpixs.png",
PIC_SIZE_DIM,
PIC_BITS,
"bwpixs");
}
This results in an incorrect image where its not only quite large for a png (about 5mb for only 1080 x 1080), but only the bottom right corner of the image is changed from black.
What am i doing wrong here ? Does libpng require any special steps for writing pngs that are only 1 in bit depth for gray scale i am not doing ?
You are calling png_write_row() way too many times. Your
for (yrow=0 ; yrow<dim_bytes ; yrow++) {
png_write_row(png_ptr, row);
++row;
}
should be something like:
for (yrow=0 ; yrow<dim_bytes ; yrow += dimen / 8) {
png_write_row(png_ptr, row);
row += dimen / 8;
}
in order to write a row of 1080 pixels (135 bytes). You were calling png_write_row() for every byte, as if the image is eight pixels wide. Which it isn't.
I am using OpenCv 2.4.8 on Linux, and obtaining a USB webcam (logitech C200) capture for further processing. I have determined that the capture uses cap_libv4.cpp (present in modlules/highgui) to capture the image. I had to modify the said file to add support for timestamps.
I have tried it with a number of webcams, and noticed it only gives correct timestamps if the flags field in the structure v4l2_buffer is 0. If it is equal to 2, which corresponds to V4L2_BUF_FLAG_TIMESTAMP MONOTONIC, it gives 0. I am wondering if it is a problem with my code modification, or with the libv4l drivers.
The function read_frame_v4l2 reads the buffer, and updates the timestamp. The timestamp can be read using the function icvGetPropertyCAM_V4L. The modified codes for these two functions are as below:
icvGetPropertyCAM_V4L:
static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
int property_id ) {
char name[32];
int is_v4l2_device = 0;
/* initialize the control structure */
switch (property_id) {
case CV_CAP_PROP_FRAME_WIDTH:
case CV_CAP_PROP_FRAME_HEIGHT:
CLEAR (capture->form);
capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
/* display an error message, and return an error code */
perror ("VIDIOC_G_FMT");
if (v4l1_ioctl (capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
fprintf (stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n");
icvCloseCAM_V4L(capture);
return -1;
} else {
int retval = (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->captureWindow.width:capture->captureWindow.height;
return retval / 0xFFFF;
}
}
return (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->form.fmt.pix.width:capture->form.fmt.pix.height;
case CV_CAP_PROP_BRIGHTNESS:
sprintf(name, "Brightness");
capture->control.id = V4L2_CID_BRIGHTNESS;
break;
case CV_CAP_PROP_CONTRAST:
sprintf(name, "Contrast");
capture->control.id = V4L2_CID_CONTRAST;
break;
case CV_CAP_PROP_SATURATION:
sprintf(name, "Saturation");
capture->control.id = V4L2_CID_SATURATION;
break;
case CV_CAP_PROP_HUE:
sprintf(name, "Hue");
capture->control.id = V4L2_CID_HUE;
break;
case CV_CAP_PROP_GAIN:
sprintf(name, "Gain");
capture->control.id = V4L2_CID_GAIN;
break;
case CV_CAP_PROP_EXPOSURE:
sprintf(name, "Exposure");
capture->control.id = V4L2_CID_EXPOSURE;
break;
case CV_CAP_PROP_POS_MSEC:
if (capture->FirstCapture) {
return 0;
} else {
return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
}
break;
default:
sprintf(name, "<unknown property string>");
capture->control.id = property_id;
}
if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
/* all went well */
is_v4l2_device = 1;
} else {
fprintf(stderr, "HIGHGUI ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
}
if (is_v4l2_device == 1) {
/* get the min/max values */
int v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
int v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
if ((v4l2_min == -1) && (v4l2_max == -1)) {
fprintf(stderr, "HIGHGUI ERROR: V4L2: Property %s(%u) not supported by device\n", name, property_id);
return -1;
}
/* all was OK, so convert to 0.0 - 1.0 range, and return the value */
return ((float)capture->control.value - v4l2_min) / (v4l2_max - v4l2_min);
} else {
/* TODO: review this section */
int retval = -1;
switch (property_id) {
case CV_CAP_PROP_BRIGHTNESS:
retval = capture->imageProperties.brightness;
break;
case CV_CAP_PROP_CONTRAST:
retval = capture->imageProperties.contrast;
break;
case CV_CAP_PROP_SATURATION:
retval = capture->imageProperties.colour;
break;
case CV_CAP_PROP_HUE:
retval = capture->imageProperties.hue;
break;
case CV_CAP_PROP_GAIN:
fprintf(stderr, "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
return -1;
break;
case CV_CAP_PROP_EXPOSURE:
fprintf(stderr, "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n");
return -1;
break;
}
if (retval == -1) {
/* there was a problem */
return -1;
}
/* all was OK, so convert to 0.0 - 1.0 range, and return the value */
return float (retval) / 0xFFFF;
}
}
read_frame_v4l2:
static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
{
static int autoindex;
autoindex = 0;
char deviceName[MAX_DEVICE_DRIVER_NAME];
if (!numCameras)
icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
if (!numCameras)
return NULL; /* Are there any /dev/video input sources? */
//search index in indexList
if ( (index>-1) && ! ((1 << index) & indexList) )
{
fprintf( stderr, "HIGHGUI ERROR: V4L: index %d is not correct!\n",index);
return NULL; /* Did someone ask for not correct video source number? */
}
/* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
the handles for V4L processing */
CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
if (!capture) {
fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n");
return NULL;
}
#ifdef USE_TEMP_BUFFER
capture->buffers[MAX_V4L_BUFFERS].start = NULL;
#endif
/* Select camera, or rather, V4L video source */
if (index<0) { // Asking for the first device available
for (; autoindex<MAX_CAMERAS;autoindex++)
if (indexList & (1<<autoindex))
break;
if (autoindex==MAX_CAMERAS)
return NULL;
index=autoindex;
autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
}
/* Print the CameraNumber at the end of the string with a width of one character */
sprintf(deviceName, "/dev/video%1d", index);
/* w/o memset some parts arent initialized - AKA: Fill it with zeros so it is clean */
memset(capture,0,sizeof(CvCaptureCAM_V4L));
/* Present the routines needed for V4L funtionality. They are inserted as part of
the standard set of cv calls promoting transparency. "Vector Table" insertion. */
capture->FirstCapture = 1;
/* set the default size */
capture->width = DEFAULT_V4L_WIDTH;
capture->height = DEFAULT_V4L_HEIGHT;
if (_capture_V4L2 (capture, deviceName) == -1) {
icvCloseCAM_V4L(capture);
capture->is_v4l2_device = 0;
if (_capture_V4L (capture, deviceName) == -1) {
icvCloseCAM_V4L(capture);
return NULL;
}
} else {
capture->is_v4l2_device = 1;
}
return capture;
}; /* End icvOpenCAM_V4L */
#ifdef HAVE_CAMV4L2
static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
/* display the error and stop processing */
perror ("VIDIOC_DQBUF");
return -1;
}
}
assert(buf.index < capture->req.count);
#ifdef USE_TEMP_BUFFER
memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
capture->buffers[buf.index].start,
capture->buffers[MAX_V4L_BUFFERS].length );
capture->bufferIndex = MAX_V4L_BUFFERS;
//printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
// buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
#else
capture->bufferIndex = buf.index;
#endif
if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
perror ("VIDIOC_QBUF");
//set timestamp in capture struct to be timestamp of most recent frame
/** where timestamps refer to the instant the field or frame was received by the driver, not the capture time*/
capture->timestamp = buf.timestamp; //
printf("Flags %0x.X, timestamp = %ld, %ld", buf.flags, buf.timestamp.tv_sec, buf.timestamp.tv_usec);
//prints 0 if the flags is of the 4th nibble from LSB is 2 i.e. of the form .....2xxx H
return 1;
}
I need the timestamp so as to determine velocity of an object I am detecting in the image. I have searched a lot and have not found any solution.
This is my first post, so I am thrilled to get some new insights and enlarge my knowledge. Currently I am working on a C-project where a binary raw file with 3d-data is loaded, processed in CUDA and saved in a new binary raw file.
This is based on the simpleTexture3D project from CUDA Samples:
This is my cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
// includes, cuda
#include <vector_types.h>
#include <driver_functions.h>
#include <cuda_runtime.h>
// CUDA utilities and system includes
#include <helper_cuda.h>
#include <helper_functions.h>
#include <vector_types.h>
typedef unsigned int uint;
typedef unsigned char uchar;
const char *sSDKsample = "simpleTexture3D";
const char *volumeFilename = "Bucky.raw";
const cudaExtent volumeSize = make_cudaExtent(32, 32, 32);
const uint width = 64, height = 64, depth=64;
//const char *volumeFilename = "TestOCT.raw";
//const cudaExtent volumeSize = make_cudaExtent(1024, 512, 512);
//
//const uint width = 1024, height = 512, depth=512;
const dim3 blockSize(8, 8, 8);
const dim3 gridSize(width / blockSize.x, height / blockSize.y, depth / blockSize.z);
uint *d_output = NULL;
int *pArgc = NULL;
char **pArgv = NULL;
extern "C" void cleanup();
extern "C" void initCuda(const uchar *h_volume, cudaExtent volumeSize);
extern "C" void render_kernel(dim3 gridSize, dim3 blockSize, uint *d_output, uint imageW, uint imageH, uint imageD);
void loadVolumeData(char *exec_path);
// render image using CUDA
void render()
{
// call CUDA kernel
render_kernel(gridSize, blockSize, d_output, width, height, depth);
getLastCudaError("render_kernel failed");
}
void cleanup()
{
// cudaDeviceReset causes the driver to clean up all state. While
// not mandatory in normal operation, it is good practice. It is also
// needed to ensure correct operation when the application is being
// profiled. Calling cudaDeviceReset causes all profile data to be
// flushed before the application exits
checkCudaErrors(cudaDeviceReset());
}
// Load raw data from disk
uchar *loadRawFile(const char *filename, size_t size)
{
FILE *fp = fopen(filename, "rb");
if (!fp)
{
fprintf(stderr, "Error opening file '%s'\n", filename);
return 0;
}
uchar *data = (uchar *) malloc(size);
size_t read = fread(data, 1, size, fp);
fclose(fp);
printf("Read '%s', %lu bytes\n", filename, read);
return data;
}
// write raw data to disk
int writeRawFile(const char *filename, uchar *data, size_t size)
{
int returnState=0;
// cut file extension from filename
char *a=strdup(filename); //via strdup you dumb a const char to char, you must free it yourself
int len = strlen(a);
a[len-4] = '\0'; //deletes '.raw'
//printf("%s\n",a);
char b[50];
sprintf(b, "_%dx%dx%d_out.raw", width, height, depth);
//char b[]="_out.raw"; //Add suffix out to filename
char buffer[256]; // <- danger, only storage for 256 characters.
strncpy(buffer, a, sizeof(buffer));
strncat(buffer, b, sizeof(buffer));
free(a);
FILE *fp = fopen(buffer, "wb"); //Open or create file for writing as binary, all existing data is cleared
if (!fp)
{
fprintf(stderr, "Error opening or creating file '%s'\n", buffer);
return 0;
}
size_t write = fwrite(data, 1, size, fp);
fclose(fp);
if (write==size)
{
printf("Wrote %lu bytes to '%s'\n", write, buffer);
return 0;
}
else
{
printf("Error writing data to file '%s'\n", buffer);
return 1;
}
}
// General initialization call for CUDA Device
int chooseCudaDevice(int argc, char **argv)
{
int result = 0;
result = findCudaDevice(argc, (const char **)argv);
return result;
}
void runAutoTest(char *exec_path, char *PathToFile)
{
// set path
char *path;
if (PathToFile == NULL)
{
path = sdkFindFilePath(volumeFilename, exec_path);
}
else
{
path = PathToFile;
}
if (path == NULL)
{
fprintf(stderr, "Error unable to find 3D Volume file: '%s'\n", volumeFilename);
exit(EXIT_FAILURE);
}
// Allocate output memory
checkCudaErrors(cudaMalloc((void **)&d_output, width*height*depth*sizeof(uchar)));
// zero out the output array with cudaMemset
cudaMemset(d_output, 0, width*height*depth*sizeof(uchar));
// render the volumeData
render_kernel(gridSize, blockSize, d_output, width, height, depth);
checkCudaErrors(cudaDeviceSynchronize());
getLastCudaError("render_kernel failed");
uchar *h_output = (uchar*)malloc(width*height*depth);
checkCudaErrors(cudaMemcpy(h_output, d_output, width*height*depth*sizeof(uchar), cudaMemcpyDeviceToHost));
int wState=writeRawFile(path,h_output,width*height*depth);
checkCudaErrors(cudaFree(d_output));
free(h_output);
// cudaDeviceReset causes the driver to clean up all state. While
// not mandatory in normal operation, it is good practice. It is also
// needed to ensure correct operation when the application is being
// profiled. Calling cudaDeviceReset causes all profile data to be
// flushed before the application exits
cudaDeviceReset();
//exit(bTestResult ? EXIT_SUCCESS : EXIT_FAILURE);
}
void loadVolumeData(char *exec_path, char *PathToFile)
{
char *path;
// load volume data
if (PathToFile == NULL)
{
path = sdkFindFilePath(volumeFilename, exec_path);
}
else
{
path = PathToFile;
}
if (path == NULL)
{
fprintf(stderr, "Error unable to find 3D Volume file: '%s'\n", volumeFilename);
exit(EXIT_FAILURE);
}
size_t size = volumeSize.width*volumeSize.height*volumeSize.depth;
uchar *h_volume = loadRawFile(path, size);
//int wState=writeRawFile(path,h_volume,size);
initCuda(h_volume, volumeSize);
free(h_volume);
}
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int
main(int argc, char **argv)
{
pArgc = &argc;
pArgv = argv;
char *image_file = NULL;
printf("%s Starting...\n\n", sSDKsample);
if (checkCmdLineFlag(argc, (const char **)argv, "file")) //Note cmd line argument is -file "PathToFile/File.raw"
{ // for example -file "C:\ProgramData\NVIDIA Corporation\CUDA Samples\v7.0\2_Graphics\simpleTexture3D_FanBeamCorr\data\TestOCT_Kopie.raw"
getCmdLineArgumentString(argc, (const char **)argv, "file", &image_file);
}
if (image_file)
{
chooseCudaDevice(argc, argv);
loadVolumeData(argv[0],image_file);
runAutoTest(argv[0],image_file);
}
else
{
// use command-line specified CUDA device, otherwise use device with highest Gflops/s
chooseCudaDevice(argc, argv);
loadVolumeData(argv[0],NULL);
runAutoTest(argv[0],NULL);
}
printf("I am finished...\n"
"Can I get some ice cream please\n");
exit(EXIT_SUCCESS);
}
And this is my .cu
#ifndef _SIMPLETEXTURE3D_KERNEL_CU_
#define _SIMPLETEXTURE3D_KERNEL_CU_
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <helper_cuda.h>
#include <helper_math.h>
typedef unsigned int uint;
typedef unsigned char uchar;
texture<uchar, 3, cudaReadModeNormalizedFloat> tex; // 3D texture
cudaArray *d_volumeArray = 0;
__global__ void
d_render(uint *d_output, uint imageW, uint imageH, uint imageD)
{
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
uint z = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;
// float u = x / (float) imageW;
// float v = y / (float) imageH;
//float w = z / (float) imageD;
// // read from 3D texture
// float voxel = tex3D(tex, u, v, w);
uint ps=__umul24(imageW,imageH);
if ((x < imageW) && (y < imageH) && (z < imageD))
{
// write output color
uint i = __umul24(z,ps) +__umul24(y, imageW) + x;
d_output[1] = (uchar) 255;//+0*voxel*255;
}
}
extern "C"
void initCuda(const uchar *h_volume, cudaExtent volumeSize)
{
// create 3D array
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<uchar>();
checkCudaErrors(cudaMalloc3DArray(&d_volumeArray, &channelDesc, volumeSize));
// copy data to 3D array
cudaMemcpy3DParms copyParams = {0};
copyParams.srcPtr = make_cudaPitchedPtr((void *)h_volume, volumeSize.width*sizeof(uchar), volumeSize.width, volumeSize.height);
copyParams.dstArray = d_volumeArray;
copyParams.extent = volumeSize;
copyParams.kind = cudaMemcpyHostToDevice;
checkCudaErrors(cudaMemcpy3D(©Params));
// set texture parameters
tex.normalized = true; // access with normalized texture coordinates
tex.filterMode = cudaFilterModeLinear; // linear interpolation
tex.addressMode[0] = cudaAddressModeBorder; // wrap texture coordinates
tex.addressMode[1] = cudaAddressModeBorder;
tex.addressMode[2] = cudaAddressModeBorder;
// bind array to 3D texture
checkCudaErrors(cudaBindTextureToArray(tex, d_volumeArray, channelDesc));
}
extern "C"
void render_kernel(dim3 gridSize, dim3 blockSize, uint *d_output, uint imageW, uint imageH, uint imageD)
{
d_render<<<gridSize, blockSize>>>(d_output, imageW, imageH, imageD);
}
#endif // #ifndef _SIMPLETEXTURE3D_KERNEL_CU_
As you can see, currently, I set all values to zero except the index = 1, which is set to 255. Yet when I now open the image stack in Fiji, I see that the fourth pixel on the first slide is white. If I use index=i instead, I get white vertical lines across the image stack periodically every four columns. Generally spoken, it seems that only every fourth element is beeing indexed in the CudaArray. So I am wondering if there is somekind of error here resulting from sizeof(uchar)=1 and sizeof(uint)=4. There would obviously be the factor 4 :)
I am eager to here from you experts
Cheers Mika
I figured it out by myself. The kernel works with uint* d_output while the copy to the host is written into a uchar* h_output
uchar *h_output = (uchar*)malloc(width*height*depth);
checkCudaErrors(cudaMemcpy(h_output, d_output, width*height*depth*sizeof(uchar), cudaMemcpyDeviceToHost));
This led to this strange behavior
I am trying to compile a project using make command.
I have several occured errors about namespace std::.
I am using Ubuntu and I think I've installed all I need to compile C++ language.
Here's the code:
#include "texture.hpp"
#include "texturefetch.hpp"
#include <png.h>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <assert.h>
#include <string>
Texture::~Texture(){
delete[] mPixels;
for (int i=1; i<mlodmax+1; ++i)
delete[] mMipMapLevels[i];
delete[] mMipMapLevels;
}
bool Texture::getclamp() const
{
return clamp;
}
void Texture::setclamp(bool value)
{
clamp = value;
}
int Texture::load(std::string filename){
FILE *fp;
png_byte magic[8];
/* open image file */
fp = std::fopen (filename.c_str(), "rb");
if (!fp) {
fprintf (stderr, "error: couldn't open \"%s\"!\n", filename.c_str());
return 0;
}
/* read magic number */
fread (magic, 1, sizeof (magic), fp);
/* check for valid magic number */
if (!png_check_sig (magic, sizeof (magic))) {
fprintf (stderr, "error: \"%s\" is not a valid PNG image!\n", filename.c_str());
fclose (fp);
return 0;
}
/* create a png read struct */
png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fclose (fp);
return 0;
}
/* create a png info struct */
png_infop info_ptr = png_create_info_struct (png_ptr);
if (!info_ptr) {
fclose (fp);
png_destroy_read_struct (&png_ptr, NULL, NULL);
return 0;
}
/* initialize the setjmp for returning properly after a libpng
error occured */
if (setjmp (png_jmpbuf (png_ptr))) {
fclose (fp);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return 0;
}
/* setup libpng for using standard C fread() function
with our FILE pointer */
png_init_io (png_ptr, fp);
/* tell libpng that we have already read the magic number */
png_set_sig_bytes (png_ptr, sizeof (magic));
/* read png info */
png_read_info (png_ptr, info_ptr);
int bit_depth, color_type;
/* get some usefull information from header */
bit_depth = png_get_bit_depth (png_ptr, info_ptr);
color_type = png_get_color_type (png_ptr, info_ptr);
/* convert index color images to RGB images */
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb (png_ptr);
/* convert 1-2-4 bits grayscale images to 8 bits
grayscale. */
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand_gray_1_2_4_to_8(png_ptr);
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha (png_ptr);
if (bit_depth == 16)
png_set_strip_16 (png_ptr);
else if (bit_depth < 8)
png_set_packing (png_ptr);
/* update info structure to apply transformations */
png_read_update_info (png_ptr, info_ptr);
/* retrieve updated information */
png_get_IHDR (png_ptr, info_ptr,
(png_uint_32*)(&mWidth),
(png_uint_32*)(&mHeight),
&bit_depth, &color_type,
NULL, NULL, NULL);
switch (color_type) {
case PNG_COLOR_TYPE_GRAY:
mPixelFormat = 1;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
mPixelFormat = 2;
break;
case PNG_COLOR_TYPE_RGB:
mPixelFormat = 3;
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
mPixelFormat = 4;
break;
default:
/* Badness */
break;
}
/* we can now allocate memory for storing pixel data */
mPixels = new unsigned char[mWidth * mHeight * mPixelFormat];
png_bytep *row_pointers;
/* setup a pointer array. Each one points at the begening of a row. */
row_pointers = new png_bytep[mHeight];
for (int i = 0; i < mHeight; ++i) {
row_pointers[i] = (png_bytep)(mPixels +
((mHeight - (i + 1)) * mWidth * mPixelFormat));
}
/* read pixel data using row pointers */
png_read_image (png_ptr, row_pointers);
/* finish decompression and release memory */
png_read_end (png_ptr, NULL);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
fclose (fp);
/* we don't need row pointers anymore */
delete[] row_pointers;
return 1;
}
Texture::Texture(std::string filename) : mPixels(NULL), mMipMapLevels(NULL), hasmipmap(false), mSu(1.f), mSv(1.f), clamp(false){
if (!load(filename)) {
std::cerr << "Erreur : impossible de lire le fichier " << filename << std::endl;
} else {
mlodmax = (int)std::floor(std::min(std::log2(mWidth), std::log2(mHeight)));
}
}
bool Texture::prefilter(){
hasmipmap = buildmipmaps();
return hasmipmap;
}
bool Texture::buildmipmaps(){
mMipMapLevels = new unsigned char*[mlodmax+1];
mMipMapLevels[0] = mPixels;
for (int i=1;i<mlodmax+1; ++i)
mMipMapLevels[i]=NULL;
// Call of the student function
return prefilterTexture(mMipMapLevels, mWidth, mHeight, mPixelFormat, mlodmax+1);
}
void Texture::setScale(float su, float sv){
mSu = 1.f/su;
mSv = 1.f/sv;
}
void Texture::getPixel(float u, float v, float lod, Color &color){
if (clamp){
u = (u>0) ? ((u<1) ? u : 1) : 0;
v = (v>0) ? ((v<1) ? v : 1) : 0;
}
u = mSu*u;
v = mSv*v;
float scaledU = u * (mWidth - 1);
float scaledV = v * (mHeight - 1);
// color = Color(u,v,0);
// return;
int s = ((int)scaledU) % mWidth;
int t = ((int)scaledV) % mHeight;
float ds = scaledU - std::floor(scaledU);
float dt = scaledV - std::floor(scaledV);
if (s<0){
s = s+mWidth;
}
if (t<0){
t = t+mHeight;
}
// Nearest
// color = interpolate(mPixels, mWidth, mHeight, s,t, 0.f,0.f);
// return;
// Linear
// color = interpolate(mPixels, mWidth, mHeight, s,t, ds, dt);
// return;
/* Filtrage */
lod = std::min(lod-1, (float)mlodmax);
if (lod > 0) {
// color = Color(0, std::floor(lod), 0);
// return;
int baselod = (int)std::floor(lod);
int pix = (int)(std::pow(2.f,baselod)); // bigger inferior mipmap level
if (hasmipmap){
// Sous-echantillonnage --> filtrage mip-map
Color color1 = integrateMipMap(baselod, ((float)s + ds)/pix, ((float)t + dt)/pix, mWidth/pix, mHeight/pix);
if (baselod < mlodmax){
pix = std::pow(2.f,baselod+1); // smaller superior mipmap level
Color color2 = integrateMipMap(baselod+1, ((float)s + ds)/pix, ((float)t + dt)/pix, mWidth/pix, mHeight/pix);
float dm = lod - std::floor(lod);
color = color1 * (1-dm) + color2 * dm;
} else {
color = color1;
}
} else {
int cs = pix * (s/pix);
int ct = pix * (t/pix);
Color color1 = integrateExplicit(mMipMapLevels[0], mWidth, mHeight, mPixelFormat, cs, ct, pix, pix);
if (baselod < mlodmax){
pix = std::pow(2.f,baselod+1); // smaller superior mipmap level
cs = pix * (s/pix);
ct = pix * (t/pix);
Color color2 = integrateExplicit(mMipMapLevels[0], mWidth, mHeight, mPixelFormat, cs, ct, pix, pix);
float dm = lod - std::floor(lod);
color = color1 * (1-dm) + color2 * dm;
} else {
color = color1;
}
}
} else {
// color = Color(1/*fabsf(lod)*/, 0, 0);
// return;
color = interpolate(mPixels, mWidth, mHeight, s,t, ds,dt);
}
}
Color Texture::integrateMipMap(int level, float s, float t, int w, int h){
Color color(0.f, 0.f, 0.f);
color = interpolate(mMipMapLevels[level], w, h, (int)s, (int)t, s-std::floor(s), t-std::floor(t));
return color;
}
Color Texture::integrateExplicit(unsigned char *pixels, int imageWidth, int imageHeight, int pixelFormat, float s, float t, int w, int h){
#if 0
Color color(0.f, 0.f, 0.f);
for (int i=0; i<h; i++)
for (int j=0; j<w; j++) {
int k = ((int)(t+i)) % imageHeight;
int l = ((int)(s+j)) % imageWidth;
int linPos = (k*imageWidth + l)*(pixelFormat);
Color centerColor(((float) pixels[linPos])/255.0, ((float) pixels[linPos+1])/255.0, ((float) pixels[linPos+2])/255.0);
color = color + centerColor;
}
color = color * (1.f/(w*h));
return color;
#endif
// Call of the student function
return integrateTexture(pixels, imageWidth, imageHeight, pixelFormat, s, t, w, h);
}
Color Texture::interpolate(unsigned char *pixels, int w, int h, int s, int t, float ds, float dt){
#if 0
Color color;
// Sur échantillonnage --> interpolation
// nearest texel
int linPos = (t*w + s)*(mPixelFormat);
Color centerColor(((float) pixels[linPos])/255.0, ((float) pixels[linPos+1])/255.0, ((float) pixels[linPos+2])/255.0);
Color rightColor;
int r = std::min(s+1, w-1);
int posds = (t*w + r)*(mPixelFormat);
rightColor = Color(
((float) pixels[posds])/255.0,
((float) pixels[posds+1])/255.0,
((float) pixels[posds+2])/255.0
);
Color upColor;
int p = std::min(t+1, h-1);
int posdt = (p*w + s)*(mPixelFormat);
upColor = Color (
((float) pixels[posdt])/255.0,
((float) pixels[posdt+1])/255.0,
((float) pixels[posdt+2])/255.0
);
Color upRightColor;
int posdtds = (p*w + r)*(mPixelFormat);
upRightColor = Color (
((float) pixels[posdtds])/255.0,
((float) pixels[posdtds+1])/255.0,
((float) pixels[posdtds+2])/255.0
);
rightColor = centerColor*(1-ds) + rightColor*ds;
upColor = upColor*(1-ds) + upRightColor*ds;
color = rightColor*(1-dt) + upColor*dt;
return color;
#endif
// Call of the student function
return interpolateTexture(pixels, w, h, mPixelFormat, (float)s+ds, (float)t+dt);
}
And here's errors in terminal:
In file included from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:0:
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp: In member function ‘float Texture::computeMipmapLevel(const Vector3D&, const Vector3D&)’:
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:55:16: error: ‘log2’ is not a member of ‘std’
return std::log2(std::max(dTdx.norm()*width()*mSu, dTdy.norm()*height()*mSv));
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:55:16: note: suggested alternative:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/vector3d.hpp:3,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:4,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:
/usr/include/x86_64-linux-gnu/bits/math-finite.h:344:15: note: ‘log2’
extern double __REDIRECT_NTH (log2, (double), __log2_finite);
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp: In constructor ‘Texture::Texture(std::string)’:
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:44: error: ‘log2’ is not a member of ‘std’
mlodmax = (int)std::floor(std::min(std::log2(mWidth), std::log2(mHeight)));
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:44: note: suggested alternative:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/vector3d.hpp:3,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:4,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:
/usr/include/x86_64-linux-gnu/bits/math-finite.h:344:15: note: ‘log2’
extern double __REDIRECT_NTH (log2, (double), __log2_finite);
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:63: error: ‘log2’ is not a member of ‘std’
mlodmax = (int)std::floor(std::min(std::log2(mWidth), std::log2(mHeight)));
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:63: note: suggested alternative:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/vector3d.hpp:3,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:4,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:
/usr/include/x86_64-linux-gnu/bits/math-finite.h:344:15: note: ‘log2’
extern double __REDIRECT_NTH (log2, (double), __log2_finite);
I took a look on internet and I tried to include and but it's still not working...
Thanks!
log2 is a C99 function. It's not in C++98, and therefore not in the std namespace. Either compile in C++11 mode (C++11 is aligned with C99):
// g++ -std=c++11
#include <cmath>
#include <iostream>
int main()
{
std::cout << std::log2(3) << std::endl;
}
... or get the function from the C header, without the namespace:
// g++ -std=c++98
#include <iostream>
#include <math.h>
int main()
{
std::cout << log2(3) << std::endl;
}
I am trying to get started with OpenAL.
I am trying to compile this program which I got from here using:
g++ main.cpp -lOpenAL
At the moment the error "AL/altypes.h" No such file or directory. Appears. Does anyone know how I can fix this? I have installed libopenal-dev. (I am on Ubuntu 13.04 I think?)
#include <iostream>
#include <cstdlib>
#include <AL/altypes.h>
#include <AL/al.h>
#include <AL/alu.h>
#include <AL/alut.h>
#define NUM_BUFFERS 1
#define NUM_SOURCES 1
#define NUM_ENVIRONMENTS 1
ALfloat listenerPos[] = {0.0, 0.0, 4.0};
ALfloat listenerVel[] = {0.0, 0.0, 0.0};
ALfloat listenerOri[] = {0.0, 0.0, 1.0, 0.0, 1.0, 0.0};
ALfloat source0Pos[] = {0.0, 0.0, 0.0};
ALfloat source0Vel[] = {0.0, 0.0, 0.0};
ALuint buffer[NUM_BUFFERS];
ALuint source[NUM_SOURCES];
ALuint environment[NUM_ENVIRONMENTS];
ALsizei size, freq;
ALenum format;
ALvoid* data;
void init(void)
{
alListenerfv(AL_POSITION,listenerPos);
alListenerfv(AL_VELOCITY,listenerVel);
alListenerfv(AL_ORIENTATION,listenerOri);
alGetError(); // clear any error messages
// Generate buffers, or else no sound will happen!
alGenBuffers(NUM_BUFFERS, buffer);
if(alGetError() != AL_NO_ERROR)
{
std::cout << "- Error creating buffers !!" << std::endl;
exit(1);
}
else
{
std::cout << "init() - No errors yet." << std::endl;
}
alutLoadWAVFile((Albyte *) "c.wav", &format, &data, size,&freq, &al_bool);
alBufferData(buffer[0],format,data,size,freq);
alutUnloadWAV(format,data,size,freq);
alGetError(); /* clear error */
alGenSources(NUM_SOURCES, source);
if(alGetError() != AL_NO_ERROR)
{
std::cout << "- Error creating sources !!" << std::endl;
exit(2);
}
else
{
std::cout << "init - no errors after alGenSources" << std::endl;
}
alSourcef(source[0], AL_PITCH, 1.0f);
alSourcef(source[0], AL_GAIN, 1.0f);
alSourcefv(source[0], AL_POSITION, source0Pos);
alSourcefv(source[0], AL_VELOCITY, source0Vel);
alSourcei(source[0], AL_BUFFER,buffer[0]);
alSourcei(source[0], AL_LOOPING, AL_TRUE);
}
int main()
{
//initialise openAL
alutInit(&argc, argv) ;
init();
return 0;
}
As an aside, this program won't actually do what I want at the moment.
I want to declare an array of double/int, populate it with data and play that data. Does anyone know how I can do that?
There is a package libalut-dev which contains utilities, however take a look at libsndfile for audio file I/O. Its always a holy grail to roll your own WAV / PCM parser which teaches you a lot and its not too difficult. WRT your aside ...the following openal code synthesizes data into an openal buffer then renders it as audio. Another page of code beyond below will get you a streaming audio player which is nice to have handy. compile it using
gcc -o gen_tone_08 gen_tone_08.c -lopenal -lm
Let us know how you get on
#include <stdio.h>
#include <stdlib.h> // gives malloc
#include <math.h>
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#elif __linux
#include <AL/al.h>
#include <AL/alc.h>
#endif
ALCdevice * openal_output_device;
ALCcontext * openal_output_context;
ALuint internal_buffer;
ALuint streaming_source[1];
int al_check_error(const char * given_label) {
ALenum al_error;
al_error = alGetError();
if(AL_NO_ERROR != al_error) {
printf("ERROR - %s (%s)\n", alGetString(al_error), given_label);
return al_error;
}
return 0;
}
void MM_init_al() {
const char * defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
openal_output_device = alcOpenDevice(defname);
openal_output_context = alcCreateContext(openal_output_device, NULL);
alcMakeContextCurrent(openal_output_context);
// setup buffer and source
alGenBuffers(1, & internal_buffer);
al_check_error("failed call to alGenBuffers");
}
void MM_exit_al() {
ALenum errorCode = 0;
// Stop the sources
alSourceStopv(1, & streaming_source[0]); // streaming_source
int ii;
for (ii = 0; ii < 1; ++ii) {
alSourcei(streaming_source[ii], AL_BUFFER, 0);
}
// Clean-up
alDeleteSources(1, &streaming_source[0]);
alDeleteBuffers(16, &streaming_source[0]);
errorCode = alGetError();
alcMakeContextCurrent(NULL);
errorCode = alGetError();
alcDestroyContext(openal_output_context);
alcCloseDevice(openal_output_device);
}
void MM_render_one_buffer() {
/* Fill buffer with Sine-Wave */
// float freq = 440.f;
float freq = 100.f;
float incr_freq = 0.1f;
int seconds = 4;
// unsigned sample_rate = 22050;
unsigned sample_rate = 44100;
double my_pi = 3.14159;
size_t buf_size = seconds * sample_rate;
short * samples = malloc(sizeof(short) * buf_size);
printf("\nhere is freq %f\n", freq);
int i=0;
for(; i<buf_size; ++i) {
samples[i] = 32760 * sin( (2.f * my_pi * freq)/sample_rate * i );
freq += incr_freq;
// incr_freq += incr_freq;
// freq *= factor_freq;
if (100.0 > freq || freq > 5000.0) {
incr_freq *= -1.0f;
}
}
/* upload buffer to OpenAL */
alBufferData( internal_buffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate);
al_check_error("populating alBufferData");
free(samples);
/* Set-up sound source and play buffer */
// ALuint src = 0;
// alGenSources(1, &src);
// alSourcei(src, AL_BUFFER, internal_buffer);
alGenSources(1, & streaming_source[0]);
alSourcei(streaming_source[0], AL_BUFFER, internal_buffer);
// alSourcePlay(src);
alSourcePlay(streaming_source[0]);
// ---------------------
ALenum current_playing_state;
alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
al_check_error("alGetSourcei AL_SOURCE_STATE");
while (AL_PLAYING == current_playing_state) {
printf("still playing ... so sleep\n");
sleep(1); // should use a thread sleep NOT sleep() for a more responsive finish
alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
al_check_error("alGetSourcei AL_SOURCE_STATE");
}
printf("end of playing\n");
/* Dealloc OpenAL */
MM_exit_al();
} // MM_render_one_buffer
int main() {
MM_init_al();
MM_render_one_buffer();
}