I am using qualcomm sdk and using the ImageTargets sample application to develop an augmented reality application. Application runs fine but i want to load another 3D model when the user touches the screen i.e. when camera view starts and comes to marker then the teapot 3D model loads and then user touches the screen a new model should load. The following are the steps i am doing :-
I have got the new 3D model and got its .h file . I have included it in assets folder
and also included it in ImageTargets.cpp file i.e. #include "./banana.h"
Then i have added ontouchEvent in ImageTargets.java file which calls another function in
ImageTargets.cpp which updates the modelID variable.
Following is the editted code of the ImageTargets.cpp in renderFrame function
#ifdef USE_OPENGL_ES_1_1
// Load projection matrix:
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(projectionMatrix.data);
// Load model view matrix:
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(modelViewMatrix.data);
glTranslatef(0.f, 0.f, kObjectScale);
glScalef(kObjectScale, kObjectScale, kObjectScale);
// Draw object:
glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
if (modeId == 0){
glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) &teapotTexCoords[0]);
glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &teapotVertices[0]);
glNormalPointer(GL_FLOAT, 0, (const GLvoid*) &teapotNormals[0]);
glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT,
(const GLvoid*) &teapotIndices[0]);
}
else{
glVertexPointer(3, GL_FLOAT, 0, bananaVerts);
glNormalPointer(GL_FLOAT, 0, bananaNormals);
//glTexCoordPointer(2, GL_FLOAT, 0, bananaTexCoords);
glDrawArrays(GL_TRIANGLES, 0 , bananaNumVerts);
}
#else
LOG("When tracker found 4");
QCAR::Matrix44F modelViewProjection;
SampleUtils::translatePoseMatrix(0.0f, 0.0f, kObjectScale,
&modelViewMatrix.data[0]);
SampleUtils::scalePoseMatrix(kObjectScale, kObjectScale, kObjectScale,
&modelViewMatrix.data[0]);
SampleUtils::multiplyMatrix(&projectionMatrix.data[0],
&modelViewMatrix.data[0] ,
&modelViewProjection.data[0]);
glUseProgram(shaderProgramID);
if (modelId == 0)
{
LOG("ModelID is 0");
glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &teapotVertices[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &teapotNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &teapotTexCoords[0]);
}
else
{
LOG("ModelID is 1");
glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &bananaVerts[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &bananaNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &bananaTexCoords[0]);
}
glEnableVertexAttribArray(vertexHandle);
glEnableVertexAttribArray(normalHandle);
glEnableVertexAttribArray(textureCoordHandle);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE,
(GLfloat*)&modelViewProjection.data[0] );
if (modelId == 0)
{
LOG("ModelID is 0");
glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT,
(const GLvoid*) &teapotIndices[0]);
}
else{
LOG("ModelID is 1");
glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);
}
SampleUtils::checkGlError("ImageTargets renderFrame");
#endif
Edit
I solved the problem though if using glDrawElements then you should not use glDrawArrays. So i created another .h file from some 3d .obj file and it started working.
Related
I use ffmpeg to decode xxx.mp4 and get YUV420p AVFrame. Then I render the yuv data by shader, but it is so green!
uTextureYLocation = glGetUniformLocation(program, uTextureY);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, yTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, avFrame->width, avFrame->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, avFrame->data[0]);
glUniform1i(uTextureYLocation, 0);
uTextureULocation = glGetUniformLocation(program, uTextureU);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, uTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, avFrame->width / 2, avFrame->height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
avFrame->data[1]);
glUniform1i(uTextureULocation, 1);
uTextureVLocation = glGetUniformLocation(program, uTextureV);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, vTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, avFrame->width / 2, avFrame->height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
avFrame->data[2]);
glUniform1i(uTextureVLocation, 2);
I'm building an Android app to render 3d (wavefront.obj) model. By using tinyobjloader, I can successfully load the model.
Code:
std::vector<glm::vec3> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
for(size_t s =0; s < shapes.size(); s++)
{
size_t index_offset = 0;
for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++)
{
int fv = shapes[s].mesh.num_face_vertices[f];
for(size_t v = 0; v < fv; v++)
{
tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
tinyobj::real_t vx = attrib.vertices[3*idx.vertex_index+0];
tinyobj::real_t vy = attrib.vertices[3*idx.vertex_index+1];
tinyobj::real_t vz = attrib.vertices[3*idx.vertex_index+2];
tinyobj::real_t nx = attrib.normals[3*idx.normal_index+0];
tinyobj::real_t ny = attrib.normals[3*idx.normal_index+1];
tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
tinyobj::real_t ux = attrib.texcoords[2*idx.texcoord_index+0];
tinyobj::real_t uy = attrib.texcoords[2*idx.texcoord_index+1];
vertices.push_back(glm::vec3(vx,vy,vz));
normals.push_back(glm::vec3(nx,ny,nz));
uvs.push_back(glm::vec2(ux,uy));
}
index_offset += fv;
}
}
Because the original .obj file has multiple faces format, i.e:
f 1/2/3 3/2/1 3/2/3
f 1/2/3 1/3/4 1/4/5 6/7/2
so that I use Blender Triangulate with 'Beauty' option to convert quad to triangle. But the rendered result is weird
I have built two function to initOpenGL (run once) and render().
initOpenGL code:
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &UVBO);
glBindBuffer(GL_ARRAY_BUFFER, UVBO);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
//Linking Vertex Attribute
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
//bind texture
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, UVBO);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
//load texture
//texture1
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if(patternSrc1)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, patWidth1, patHeight1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
patternSrc1);
//glGenerateMipmap(GL_TEXTURE_2D);
}
render() code:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
camera.ProcessOneFinger(moveStpX, moveStpY);
camera.ProcessTwoFinger(move2X, move2Y);
projection = glm::perspective(camera.GetZoom(), (GLfloat)600/(GLfloat)1024, nearPlane, farPlane);
view = camera.GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
GLfloat angle = 20.0f;
model = glm::rotate(model, angle, glm::vec3( 1.0f, 0.3f, 0.5f));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr( model ) );
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
Model detail
Texture:
Model.obj file after triangulated:
https://pastebin.com/vUjHv8Fr
Thank you!!!
This looks to me like your texture is upside down. There's basically two potential errors that could each lead to this happening. Most likely, the texture image itself is upside down, e.g., because the image data passed to glTexImage2D() is in the wrong order. Unlike most other APIs, OpenGL (by default) expects pixel data in row-wise order starting from the bottom row. Check the way you load the texture data to make sure it's in the right order.
If this is not the problem, then it might be that your texture coordinates are for a left-handed texture coordinate system. OpenGL, however, uses right-handed texture coordinates where the origin is the lower-left corner of the texture image rather than the upper left corner. I'm not a Blender guy, but there's probably an export setting for this…
I have an Android application, that render some 3D-model, loaded from OBJ-file. At first I try to render only vertices (without normals and texture-coord info).
After loading OBJ-file vertices to vector of triangles I try to create VBO:
struct obj_model_t {
GLuint vertex_buf;
GLuint tex_coord_buf;
GLuint normals_buf;
unsigned int count;
};
...
obj_model_t out_model;
// loading triangles to std::vector<glm::vec3> out_vertices;
glGenBuffers(1, &out_model.vertex_buf);
glBindBuffer(GL_ARRAY_BUFFER, out_model.vertex_buf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * out_vertices.size(), &out_vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
And then, in render function I try to bind this VBO and draw triangles from that:
void engine_t::render(double elapsedTime) {
// clear buffer and other preparations for render
mat4 mvp = camera_.projection_matrix() * camera_.view_matrix();
glUseProgram(gProgram);
checkGlError("glUseProgram");
glUniformMatrix4fv(g_uMVPMatrix_Handle, 1, GL_FALSE, &mvp[0][0]);
glBindBuffer(GL_ARRAY_BUFFER, model_.vertex_buf);
checkGlError("glBindBuffer");
glEnableVertexAttribArray(g_vPosition_Handle);
checkGlError("glEnableVertexAttribArray");
glVertexAttribPointer(g_vPosition_Handle, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
checkGlError("glVertexAttribPointer");
glDrawArrays(GL_TRIANGLES, 0, model_.count); // E/Adreno200-ES20(27772): gl_draw_error_checks:418>: GL_INVALID_OPERATION
checkGlError("glDrawArrays"); // after glDrawArrays glError (0x502)
glDisableVertexAttribArray(g_vPosition_Handle);
checkGlError("glDisableVertexAttribArray");
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
But if I replace out_vertices from loading function to global space and use:
glVertexAttribPointer(g_vPosition_Handle, 3, GL_FLOAT, GL_FALSE, 0, (void *)&out_vertices[0]);
without binding model_.vertex_buf (without call glBindBuffer(GL_ARRAY_BUFFER, model_.vertex_buf);) my model renders normally.
How I can fix this problem and use VBO to draw my vertices?
I'm trying to apply a texture to an object in opengl es from the native side and I have no idea why it isn't showing up. I have a couple random objects drawn on the screen, and they're all visible and everything. I applied color to some shapes using glColor4f and that works fine. I'm trying to use a texture on the last object that gets drawn but it ends up being the same color as the one previous.
I was originally loading the texture from a png, but I decided to simplify things by loading it from a file that contains raw RGB data. It's 16 pixels x 16 pixels, and I've tried sizes up to 512 by 512 with the same result.
Here's how I'm initializing everything:
bool Activity::_initGL () {
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLint dummy, format;
EGLint numConfigs;
EGLConfig config;
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(app->window, 0, 0, format);
surface = eglCreateWindowSurface(display, config, app->window, NULL);
context = eglCreateContext(display, config, NULL, NULL);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGE("Unable to eglMakeCurrent");
return false;
}
eglQuerySurface(display, surface, EGL_WIDTH, &width);
eglQuerySurface(display, surface, EGL_HEIGHT, &height);
glViewport(0,0, width, height);
}
And then I enable the necessary things and try to create the texture:
void postInit () {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glDisable( GL_BLEND );
glDisable( GL_LIGHTING );
// glEnable(GL_CULL_FACE);
glEnable( GL_TEXTURE_2D );
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
glClearColor(0,0,0,1);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glMatrixMode( GL_MODELVIEW );
GLuint texIDarray[1];
glGenTextures( 1, texIDarray );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, texIDarray[0] );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)16, (GLsizei)16, 0, GL_RGB, GL_UNSIGNED_BYTE, protData);
}
And here's where the texture gets drawn, someday:
void drawImpl () {
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
// glDisable(GL_TEXTURE_2D);
// glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// glEnableClientState(GL_VERTEX_ARRAY);
// glViewport(0, 0, wid, hei);
#define fX(x) ((int)(x * (1 << 16)))
static int verts[6] = {
0,0,
65536,0,
0,30000
};
glVertexPointer(2, GL_FIXED, 0, verts);
// glColor4f(1,0,1,1);
glDrawArrays(GL_TRIANGLES, 0, 3);
static int poo[12] = {
40000,-5000,
40000,-30000,
60000,-5000,
60000,-5000,
40000,-30000,
60000,-30000
};
glVertexPointer(2, GL_FIXED, 0, poo);
// glColor4f(1,1,1,1);
glDrawArrays(GL_TRIANGLES, 0, 6);
static int pee[12] = {
40000, 5000,
60000, 5000,
60000,30000,
40000, 5000,
60000,30000,
40000,30000
};
glVertexPointer(2, GL_FIXED, 0, pee);
// glColor4f(1,0,1,1);
glDrawArrays(GL_TRIANGLES, 0, 6);
glEnable(GL_TEXTURE_2D);
static int squareVerts[12] = {
0,0,
fX(1),0,
0,fX(1),
0,fX(1),
fX(1),0,
fX(1),fX(1)
};
static int texCoords[12] = {
0,0,
fX(1),0,
0,fX(1),
0,fX(1),
fX(1),0,
fX(1),fX(1)
};
//glTranslatef( (float)-.25, (float)-.5, (float)0);
// glColor4f(0,0,0,0);
// glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTexture( GL_TEXTURE0 );
// glBindTexture(GL_TEXTURE_2D, texID);
glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameterx( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterx( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glVertexPointer(2, GL_FIXED, 0, squareVerts);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
// glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable( GL_TEXTURE_2D );
glDrawArrays(GL_TRIANGLES, 0, 6);
// glDisableClientState(GL_VERTEX_ARRAY);
// glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
I deliberately left some of the commented out things to show the other things I have tried doing.
I am totally at a dead end with this right now. If anyone has any suggestions or anything it would make me super happy, and that is good.
Seems like you messed up your texture coordinates.. They should be between 0 and 1, not between 0 and 1<<16. Another thing is your "glColor4f" will also affect your texture by modulating it and for normal texture draw it needs to be set to (1,1,1,1).
I am trying to display a texture on a square using opengl es 1 using the ndk.
I am using this "hacks" to load a png from the apk : http://www.anddev.org/ndk_opengl_-_loading_resources_and_assets_from_native_code-t11978.html
This seems to work fine.
When i want to apply the texture to my quad, the texture seems to be duplicate.
After some research i think the problem is coming from my rendering code :
//the order is correct even if it is not in the numeric order
GLfloat vertexBuffer[] = {
_vertices[0].x, _vertices[0].y,
_vertices[3].x, _vertices[3].y,
_vertices[1].x, _vertices[1].y,
_vertices[2].x, _vertices[2].y,
};
GLfloat texCoords[] = {
0.0, 1.0, // left-bottom
1.0, 1.0, // right-bottom
0.0, 0.0, // left-top
1.0, 0.0 // right-top
};
glBindTexture(GL_TEXTURE_2D, _texture->getTexture());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, 0);
The problem was definitly is the png loading function.
I add a test to check if the image contain an alpha channel using the libpng :
bool hasAlpha;
switch (info_ptr->color_type) {
case PNG_COLOR_TYPE_RGBA:
hasAlpha = true;
break;
case PNG_COLOR_TYPE_RGB:
hasAlpha = false;
break;
default:
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
zip_fclose(file);
return TEXTURE_LOAD_ERROR;
}
And i changed the glTexImage2D parameters "internalformat" and "format":
glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? GL_RGBA : GL_RGB, width, height, 0, hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image_data);