Tessellation - saving data - c++

I am using tessellation in order to transfer non triangled polygons to triangle polygons.
I am trying to save the data in variable and run the tessellation code once while saving the data. The code use the saved data in order to draw it in draw function.
I am trying the draw a star polygon, The problem is that I can see some triangles but not a star. Why when I save the data the drawing go wrong?
Here is the initialize code:
#define callback void(CALLBACK*)()
void Init()
{
GLdouble star[5][6] = /* star data, The data is 100% perfect */
glColor3f(0.0f, 1.0f, 0.0f);
GLUtesselator *pTess = gluNewTess();
indexNum = 0;
gluTessCallback(pTess, GLU_TESS_BEGIN, (callback)glDrowMode);
gluTessCallback(pTess, GLU_TESS_VERTEX, (callback)saveData);
gluTessCallback(pTess, GLU_TESS_ERROR, (callback)tessError);
gluTessCallback(pTess, GLU_TESS_COMBINE, (callback) scbCombine);
gluTessProperty(pTess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
gluTessBeginPolygon(pTess, NULL);
gluTessBeginContour(pTess);
for(int i = 0; i < 5; i++)
gluTessVertex(pTess, star[i], star[i]);
gluTessEndContour(pTess);
gluTessEndPolygon(pTess);
gluDeleteTess(pTess);
}
The saving data code and saving the drawing mode:
struct vecStruct
{
GLdouble *vertex, *color;
};
vecStruct vec[16];
int indexNum = 0;
void CALLBACK saveData(const GLvoid *ptr)
{
const GLdouble *data = (const GLdouble*)ptr;
vec[indexNum].vertex = new GLdouble[3];
vec[indexNum].color = new GLdouble[3];
vec[indexNum].vertex[0] = data[0];
vec[indexNum].vertex[1] = data[1];
vec[indexNum].vertex[2] = data[2];
vec[indexNum].color[0] = data[3];
vec[indexNum].color[1] = data[4];
vec[indexNum].color[2] = data[5];
indexNum++;
}
GLenum drawMode;
void CALLBACK glDrowMode(GLenum where)
{
drawMode = where;
}
And last the drow function:
void vboDraw()
{
glBegin(drawMode);
for (int i = 0; i < indexNum; i++)
{
glColor3dv(vec[i].color);
glVertex3dv(vec[i].vertex);
}
glEnd();
}
As I have said I should see star:
But what I can see is some triangles:
What is wrong with the code?
Why can not I save the data for doing the tessellation code only once?

Related

OpenGL imgui slider ranges

I have a 960x540 window I'm creating using OpenGL. Rendering one texture here and using imgui to implement a slider that let's me translate the x, y, and z positions at runtime.
int window_width = 960;
int window_height = 540;
window = glfwCreateWindow(window_width, window_height, "Object Oriented OpenGL", NULL, NULL);
First I set the slider default values.
glm::vec3 model_matrix_translation(200, 200, 0);
Later in my loop that renders the objects positions frame by frame as long as the window is open, I set the ImGui::SliderFloat3 v_min and v_max params to be the dimensions of my window. It appears all 3 sliders x,y, and z use these values, but is there a way to set a range for each individuals slider? As you can see my slider for the y axis can go beyond 540.
while (!glfwWindowShouldClose(window))
{
// renderer and other code before this point
{
ImGui::SliderFloat3("Model Matrix Translation", &model_matrix_translation.x, 0.0f, 960.0f);
}
ImGui::Render();
ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
glfwPollEvents();
}
The implementation of SliderFloat3 delegates to SliderScalarN, which is implemented as such:
bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
bool value_changed = false;
BeginGroup();
PushID(label);
PushMultiItemsWidths(components, CalcItemWidth());
size_t type_size = GDataTypeInfo[data_type].Size;
for (int i = 0; i < components; i++)
{
PushID(i);
if (i > 0)
SameLine(0, g.Style.ItemInnerSpacing.x);
value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, power);
PopID();
PopItemWidth();
v = (void*)((char*)v + type_size);
}
PopID();
const char* label_end = FindRenderedTextEnd(label);
if (label != label_end)
{
SameLine(0, g.Style.ItemInnerSpacing.x);
TextEx(label, label_end);
}
EndGroup();
return value_changed;
}
For your purposes, you will need to use a modified version of this function that moves v_min and v_max along with v, so in your modified function, change the last line of that for loop to:
v = (void*)((char*)v + type_size);
v_min = (void*)((char*)v_min + type_size);
v_max = (void*)((char*)v_max + type_size);
Or just specialize the whole function to take float* instead and then you can just do v++, v_min++, v_max++; instead.
Finally, you can call your modified function as follows:
float mins[] = {0.0f, 0.0f, 0.0f};
float maxs[] = {960.0f, 540.0f, 0.0f};
MyModifiedSliderFloat3("Model Matrix Translation", &model_matrix_translation.x, mins, maxs);

Ray Tracing using Nvidia Optix with Open Asset Import Library (assimp) - rendering multiple meshes

I'm trying to combine the versatility of Open Asset Import Library (reading in a variety of 3D model filetypes) with NVidia Optix ray tracing to render the models.
So far, it is working whenever the model I'm rendering is made up of a single mesh. When I try to render a file with more than one mesh, I get only partial results. I can't narrow down where the issue is, looking for some insight. Relevant code here:
Loading a file using assimp importer and creating the optix buffers:
int loadAsset(const char* path)
{
Assimp::Importer importer;
scene = importer.ReadFile(
path,
aiProcess_Triangulate
//| aiProcess_JoinIdenticalVertices
| aiProcess_SortByPType
| aiProcess_ValidateDataStructure
| aiProcess_SplitLargeMeshes
| aiProcess_FixInfacingNormals
);
if (scene) {
getBoundingBox(&scene_min, &scene_max);
scene_center.x = (scene_min.x + scene_max.x) / 2.0f;
scene_center.y = (scene_min.y + scene_max.y) / 2.0f;
scene_center.z = (scene_min.z + scene_max.z) / 2.0f;
float3 optixMin = { scene_min.x, scene_min.y, scene_min.z };
float3 optixMax = { scene_max.x, scene_max.y, scene_max.z };
aabb.set(optixMin, optixMax);
unsigned int numVerts = 0;
unsigned int numFaces = 0;
if (scene->mNumMeshes > 0) {
printf("Number of meshes: %d\n", scene->mNumMeshes);
// get the running total number of vertices & faces for all meshes
for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
numVerts += scene->mMeshes[i]->mNumVertices;
numFaces += scene->mMeshes[i]->mNumFaces;
}
printf("Found %d Vertices and %d Faces\n", numVerts, numFaces);
// set up buffers
optix::Buffer vertices = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, numVerts);
optix::Buffer normals = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, numVerts);
optix::Buffer faces = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT3, numFaces);
optix::Buffer materials = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, numVerts);
// unused buffer
Buffer tbuffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 0);
// create material
std::string defaultPtxPath = "C:\\ProgramData\\NVIDIA Corporation\\OptiX SDK 4.1.0\\SDK\\build\\lib\\ptx\\";
Program phong_ch = context->createProgramFromPTXFile(defaultPtxPath + "optixPrimitiveIndexOffsets_generated_phong.cu.ptx", "closest_hit_radiance");
Program phong_ah = context->createProgramFromPTXFile(defaultPtxPath + "optixPrimitiveIndexOffsets_generated_phong.cu.ptx", "any_hit_shadow");
Material matl = context->createMaterial();
matl->setClosestHitProgram(0, phong_ch);
matl->setAnyHitProgram(1, phong_ah);
matl["Kd"]->setFloat(0.7f, 0.7f, 0.7f);
matl["Ka"]->setFloat(1.0f, 1.0f, 1.0f);
matl["Kr"]->setFloat(0.0f, 0.0f, 0.0f);
matl["phong_exp"]->setFloat(1.0f);
std::string triangle_mesh_ptx_path(ptxPath("triangle_mesh.cu"));
Program meshIntersectProgram = context->createProgramFromPTXFile(triangle_mesh_ptx_path, "mesh_intersect");
Program meshBboxProgram = context->createProgramFromPTXFile(triangle_mesh_ptx_path, "mesh_bounds");
optix::float3 *vertexMap = reinterpret_cast<optix::float3*>(vertices->map());
optix::float3 *normalMap = reinterpret_cast<optix::float3*>(normals->map());
optix::uint3 *faceMap = reinterpret_cast<optix::uint3*>(faces->map());
unsigned int *materialsMap = static_cast<unsigned int*>(materials->map());
context["vertex_buffer"]->setBuffer(vertices);
context["normal_buffer"]->setBuffer(normals);
context["index_buffer"]->setBuffer(faces);
context["texcoord_buffer"]->setBuffer(tbuffer);
context["material_buffer"]->setBuffer(materials);
Group group = createSingleGeometryGroup(meshIntersectProgram, meshBboxProgram, vertexMap,
normalMap, faceMap, materialsMap, matl);
context["top_object"]->set(group);
context["top_shadower"]->set(group);
vertices->unmap();
normals->unmap();
faces->unmap();
materials->unmap();
}
return 0;
}
return 1;
}
And the relevant function for creating the geometries and filling the buffers:
Group createSingleGeometryGroup(Program meshIntersectProgram, Program meshBboxProgram, optix::float3 *vertexMap,
optix::float3 *normalMap, optix::uint3 *faceMap, unsigned int *materialsMap, Material matl) {
Group group = context->createGroup();
optix::Acceleration accel = context->createAcceleration("Trbvh");
group->setAcceleration(accel);
std::vector<GeometryInstance> gis;
unsigned int vertexOffset = 0u;
unsigned int faceOffset = 0u;
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
aiMesh *mesh = scene->mMeshes[m];
if (!mesh->HasPositions()) {
throw std::runtime_error("Mesh contains zero vertex positions");
}
if (!mesh->HasNormals()) {
throw std::runtime_error("Mesh contains zero vertex normals");
}
printf("Mesh #%d\n\tNumVertices: %d\n\tNumFaces: %d\n", m, mesh->mNumVertices, mesh->mNumFaces);
// add points
for (unsigned int i = 0u; i < mesh->mNumVertices; i++) {
aiVector3D pos = mesh->mVertices[i];
aiVector3D norm = mesh->mNormals[i];
vertexMap[i + vertexOffset] = optix::make_float3(pos.x, pos.y, pos.z) + aabb.center();
normalMap[i + vertexOffset] = optix::normalize(optix::make_float3(norm.x, norm.y, norm.z));
materialsMap[i + vertexOffset] = 0u;
}
// add faces
for (unsigned int i = 0u; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
// add triangles
if (face.mNumIndices == 3) {
faceMap[i + faceOffset] = optix::make_uint3(face.mIndices[0], face.mIndices[1], face.mIndices[2]);
}
else {
printf("face indices != 3\n");
faceMap[i + faceOffset] = optix::make_uint3(-1);
}
}
// create geometry
optix::Geometry geometry = context->createGeometry();
geometry->setPrimitiveCount(mesh->mNumFaces);
geometry->setIntersectionProgram(meshIntersectProgram);
geometry->setBoundingBoxProgram(meshBboxProgram);
geometry->setPrimitiveIndexOffset(faceOffset);
optix::GeometryInstance gi = context->createGeometryInstance(geometry, &matl, &matl + 1);
gis.push_back(gi);
vertexOffset += mesh->mNumVertices;
faceOffset += mesh->mNumFaces;
}
printf("VertexOffset: %d\nFaceOffset: %d\n", vertexOffset, faceOffset);
// add all geometry instances to a geometry group
GeometryGroup gg = context->createGeometryGroup();
gg->setChildCount(static_cast<unsigned int>(gis.size()));
for (unsigned i = 0u; i < gis.size(); i++) {
gg->setChild(i, gis[i]);
}
Acceleration a = context->createAcceleration("Trbvh");
gg->setAcceleration(a);
group->setChildCount(1);
group->setChild(0, gg);
return group;
}
Running the above code on a sample file from assimp (using the dwarf.x, file contains 2 meshes) yields this result:
You can see only part of the second mesh (the dwarf's body) is rendered. I tried rendering each mesh separately, one at a time, and they render in full. But when putting them together I get this.
I'm thinking the issue is either with creating the geometry, perhaps I have these lines wrong:
geometry->setPrimitiveCount(mesh->mNumFaces);
geometry->setPrimitiveIndexOffset(faceOffset);
or the assimp postprocessing flags
scene = importer.ReadFile(
path,
aiProcess_Triangulate
//| aiProcess_JoinIdenticalVertices
| aiProcess_SortByPType
| aiProcess_ValidateDataStructure
| aiProcess_SplitLargeMeshes
| aiProcess_FixInfacingNormals
);
(note above, I had to comment out JoinIdenticalVertices because it gave me a horribly wrong result shown below):
Has anyone been able to successfully combine nvidia optix with open asset import library for rendering files with multiple meshes?
I found a solution, although not sure how optimal.
Each mesh still gets its own geometry, however instead of creating single vertex, index and normal buffers which are shared among all geometries, I create separate buffers for each geometry.
Then, instead of
context["vertex_buffer"]->setBuffer(vertices);
context["normal_buffer"]->setBuffer(normals);
context["index_buffer"]->setBuffer(faces);
context["texcoord_buffer"]->setBuffer(tbuffer);
context["material_buffer"]->setBuffer(materials);
I use
geometry["vertex_buffer"]->setBuffer(vertices);
geometry["normal_buffer"]->setBuffer(normals);
geometry["index_buffer"]->setBuffer(faces);
geometry["texcoord_buffer"]->setBuffer(tbuffer);
geometry["material_buffer"]->setBuffer(materials);
The result:

glutesselator always crashes at gluTessEndPolygon() [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I use glu tessellation to tessellate complex polygons. The code simplified is listed bellow.
It always crashes at gluTessEndPolygon(GLUtessobj) with error:
Error: 0xC0000005: Access violation reading location 0x57783b39;
The code works when the number of points of the polygon is small (<100).
I just can't figure out why.
typedef boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian> pt;
typedef boost::geometry::model::polygon<pt> Polygon;
typedef boost::geometry::model::ring<pt> Ring;
vector<Polygon> g_myPolys;
// ------Static variables used in glu tessellation------
static GLUtesselator *GLUtessobj;
static unsigned int s_gltri_type;
static int s_tess_orient;
static int s_cur_pt_idx;
// Create an array to hold pointers to allocated vertices created by "combine" callback,
// so that they may be deleted after tessellation.
static std::vector<GLdouble*> s_combineVertexArray;
// Store tessellated results
static std::vector<double> s_vecTriVerts; // Store area objects' tessellated triangle( triangle fan, triangle strip and triangles) vertices.
static std::vector<int> s_vecTriStripVertCnts; // Store every triangle strips' start indices in m_vecTriVerts.
static std::vector<int> s_vecTriStripFirstIdx; // Store every triangle strips' vertex count start from its start index.
static std::vector<int> s_vecTriFanVertCnts; // Store every triangle fans' start indices in m_vecTriVerts.
static std::vector<int> s_vecTriFanFirstIdx; // Store every triangle fans' vertex count start from its start index.
static std::vector<int> s_vecTrisVertCnts; // Store every triangles' start indices in m_vecTriVerts.
static std::vector<int> s_vecTrisFirstIdx; // Store every triangles' vertex count start from its start index.
static int s_cur_tri_fans_vert_cnt;
static int s_cur_tri_strips_vert_cnt;
static int s_cur_tris_vert_cnt;
static std::vector<double*> s_vecTmp;
void beginCallback(GLenum which)
{
s_gltri_type = which;
switch ( s_gltri_type)
{
case GL_TRIANGLE_FAN:
s_vecTriFanFirstIdx.push_back(s_cur_pt_idx);
s_cur_tri_fans_vert_cnt = 0;
break;
case GL_TRIANGLE_STRIP:
s_vecTriStripFirstIdx.push_back(s_cur_pt_idx);
s_cur_tri_strips_vert_cnt = 0;
break;
case GL_TRIANGLES:
s_vecTrisFirstIdx.push_back(s_cur_pt_idx);
s_cur_tris_vert_cnt = 0;
break;
}
}
void vertexCallback(GLvoid *vertex)
{
GLdouble *pv = (GLdouble *) vertex;
s_vecTriVerts.push_back(pv[0]);
s_vecTriVerts.push_back(pv[1]);
s_cur_pt_idx ++;
switch ( s_gltri_type)
{
case GL_TRIANGLE_FAN:
s_cur_tri_fans_vert_cnt ++;
break;
case GL_TRIANGLE_STRIP:
s_cur_tri_strips_vert_cnt ++;
break;
case GL_TRIANGLES:
s_cur_tris_vert_cnt ++;
break;
}
}
void combineCallback(GLdouble coords[3],
GLdouble *vertex_data[4],
GLfloat weight[4], GLdouble **dataOut )
{
GLdouble *vertex = (GLdouble *)malloc(6 * sizeof(GLdouble));
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
vertex[3] = vertex[4] = vertex[5] = 0.0;
*dataOut = vertex;
s_combineVertexArray.push_back(vertex);
}
void endCallback()
{
switch ( s_gltri_type)
{
case GL_TRIANGLE_FAN:
s_vecTriFanVertCnts.push_back(s_cur_tri_fans_vert_cnt);
break;
case GL_TRIANGLE_STRIP:
s_vecTriStripVertCnts.push_back(s_cur_tri_strips_vert_cnt);
break;
case GL_TRIANGLES:
s_vecTrisVertCnts.push_back(s_cur_tris_vert_cnt);
break;
}
}
void errorCallback(GLenum errorCode)
{
const GLubyte *estring;
estring = gluErrorString(errorCode);
printf ("Tessellation Error: %s\n", estring);
}
void Tessellate()
{
// Create tessellate object
GLUtessobj = gluNewTess();
// Register the callbacks
gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (void (__stdcall*)())&beginCallback);
gluTessCallback(GLUtessobj, GLU_TESS_VERTEX, (void (__stdcall*)())&vertexCallback);
gluTessCallback(GLUtessobj, GLU_TESS_END, (void (__stdcall*)())&endCallback);
gluTessCallback(GLUtessobj, GLU_TESS_COMBINE, (void (__stdcall*)())&combineCallback);
gluTessCallback(GLUtessobj, GLU_TESS_ERROR, (void (__stdcall*)())&errorCallback);
gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
gluTessBeginPolygon(GLUtessobj, NULL);
gluTessBeginContour(GLUtessobj);
Polygon pp = g_myPolys[0];
for ( int i = 0; i < pp.outer().size(); i ++)
{
GLdouble *p = new GLdouble[3];
s_vecTmp.push_back(p);
p[0] = pp.outer()[i].get<0>();
p[1] = pp.outer()[i].get<1>();
p[2] = 0.0;
gluTessVertex( GLUtessobj, p, p ) ;
}
gluTessEndContour(GLUtessobj);
gluTessEndPolygon(GLUtessobj);
gluDeleteTess(GLUtessobj);
for ( int i = 0; i < s_vecTmp.size(); i ++)
delete[] s_vecTmp[i];
s_vecTmp.clear();
// Free up any "Combine" vertices created
for(unsigned int i = 0; i < s_combineVertexArray.size(); i++)
free (s_combineVertexArray[i]);
s_combineVertexArray.clear();
}
One thing that immediately strikes me as odd is, that you do the cast to __stdcall there.
gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (void (__stdcall*)())&beginCallback);
Why are you doing that? If your compiler complains about incompatible calling conventions, then the last thing you should do there is casting the calling convention. Only despair and horror await if you cast a calling convention. It's already a bad idea to cast pointers (in C++ casting from/to void* is kind of okay, but that's it).
And then there are a few other weird things you do with pointers. For example you're mixing std::vector with manually managed memory (new GLdouble[3]). Seriously, why?!
I strongly suggest you simplify your data structures and clean up that pointer juggling. Most likely you have some out of bounds buffer write somewhere in your code, but it's difficult to see where exactly.

OpenGL Picking on Selection Mode

I know that OpenGL selection mode is deprecated and never was HW accelerated, except on a few SGI boxes and 3DLabs GPUs.But i can't get rid of it (not my code).Below its the C++ code:
void GLWidget::Selection(int x,int y) // This Is Where Selection Is Done
{
GLint viewport[4];
glSelectBuffer(BUFSIZE,selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT,viewport);
gluPickMatrix(x,viewport[3]-y,5,5,viewport); //defining the picking matrix
gluPerspective(fov,ratio,0.1f,1000);
glMatrixMode(GL_MODELVIEW);
glInitNames();
glPushName(1); //Pushing names on the stack
glutSolidTorus(1, 2, 55, 55); //Some draw in GL_SELECT mode
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(2);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(3);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2); //public members
glTranslatef(5.0f,1,5.0f);
glPopName();
int hits;
// restoring the original projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
// returning to normal rendering mode
hits = glRenderMode(GL_RENDER);
// if there are hits process them
if (hits != 0){
qDebug() << "Found " << hits << " hit(s)";
processHits(hits,selectBuf);
}
}
This is the processHits method
void GLWidget::processHits (GLint hits, GLuint buffer[]) //Some prints
{
unsigned int i, j;
GLuint names, *ptr, minZ,*ptrNames, numberOfNames;
ptr = (GLuint *) buffer;
minZ = 0xffffffff;
for (i = 0; i < hits; i++) {
names = *ptr;
ptr++;
if (*ptr < minZ) {
numberOfNames = names;
minZ = *ptr;
ptrNames = ptr+2;
}
ptr += names+2;
}
qDebug() << "Nearest: ";
ptr = ptrNames;
for (j = 0; j < numberOfNames; j++,ptr++) {
qDebug() << *ptr ;
}
}
Selection() is invoked by using an *event (GLWidget derives from QGLWidget (QT 4.8)).
So,only when i click the right mousebutton I ""draw"" objects in the buffer and push their names on the stack.
void GLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
if (event->buttons() & GLUT_RIGHT_BUTTON){
Selection(event->x(),event->y());
}
}
While the paintGL() method is
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glViewport (0, 0, w_screen, h_screen);
gluLookAt(objCamera->mPos.x, objCamera->mPos.y, objCamera->mPos.z,
0, objCamera->mView.y, 0,
objCamera->mUp.x, objCamera->mUp.y, objCamera->mUp.z);
glutSolidTorus(1, 2, 55, 55); //draw some objects
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2);
glTranslatef(5.0f,1,5.0f);
glTranslatef(-15.0f,-3,-15.0f);
}
At this time,with this code, I can select an object and retrieve its ID,and if there are more of them on the same xy coordinates i can retrieve the nearest one (by ID).
So,now I've got 3 objects with 3 different IDs (1-2-3).
The one with ID=3 has non fixed size.My question is:how to use the buffer to retrieve the third torus and change its size modifying RADIUS1, RADIUS2, complex1, complex2?
Could someone of you write a small example?
Have I,when there is a hit,simply use the name of the hit on the stack (given with glPushName),that must refers in some way to an object (maybe with a string public member wich contains the name),so i can change its properties?
You are going to have to store the properties of each object yourself. When you push a name onto the name stack, all you're doing is adding extra data to each fragment so you can effectively identify where it came from later.
You'll probably want to create a structure like { float rad1, rad2, complex1, complex2; } to store the values for each torus. Once you know the ID of the object selected, go into your array of said struct, and modify the values for the appropriate object. Each time you draw your scene, just run through this array of structs.

texture problems with librocket, ogre & ios

We are trying to use librocket http://librocket.com/ together with Ogre http://www.ogre3d.org/. They're both part of gamekit http://code.google.com/p/gamekit/ which I use for this project.
This all works fine together as long as I don't load an image with librocket. As soon as I do that the viewport on the iPad is not fullscreen anymore but small in the lower corner. Like this: http://uploads.undef.ch/machine/ipad.png
I can't make a connection between loading/rendering a texture and resizing of the viewport. And I can't find anything wrong with the RenderInterface. http://uploads.undef.ch/machine/RenderInterfaceOgre3D.cpp
Is there any OpenGLES command that could have an affect on the active viewport size?
This is the relevant code that loads an image and displays it:
// Called by Rocket when a texture is required by the library.
bool RenderInterfaceOgre3D::LoadTexture(Rocket::Core::TextureHandle& texture_handle, Rocket::Core::Vector2i& texture_dimensions, const Rocket::Core::String& source)
{
Ogre::TextureManager* texture_manager = Ogre::TextureManager::getSingletonPtr();
Ogre::TexturePtr ogre_texture = texture_manager->getByName(Ogre::String(source.CString()));
if (ogre_texture.isNull())
{
ogre_texture = texture_manager->load(Ogre::String(source.CString()),
DEFAULT_ROCKET_RESOURCE_GROUP,
Ogre::TEX_TYPE_2D,
0);
}
if (ogre_texture.isNull())
return false;
texture_dimensions.x = ogre_texture->getWidth();
texture_dimensions.y = ogre_texture->getHeight();
texture_handle = reinterpret_cast<Rocket::Core::TextureHandle>(new RocketOgre3DTexture(ogre_texture));
return true;
}
// Called by Rocket when it wants to render geometry that it does not wish to optimise.
void RenderInterfaceOgre3D::RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation)
{
// We've chosen to not support non-compiled geometry in the Ogre3D renderer.
// But if you want, you can uncomment this code, so borders will be shown.
/*
Rocket::Core::CompiledGeometryHandle gh = CompileGeometry(vertices, num_vertices, indices, num_indices, texture);
RenderCompiledGeometry(gh, translation);
ReleaseCompiledGeometry(gh);
*/
}
// Called by Rocket when it wants to compile geometry it believes will be static for the forseeable future.
Rocket::Core::CompiledGeometryHandle RenderInterfaceOgre3D::CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture)
{
RocketOgre3DCompiledGeometry* geometry = new RocketOgre3DCompiledGeometry();
geometry->texture = texture == NULL ? NULL : (RocketOgre3DTexture*) texture;
geometry->render_operation.vertexData = new Ogre::VertexData();
geometry->render_operation.vertexData->vertexStart = 0;
geometry->render_operation.vertexData->vertexCount = num_vertices;
geometry->render_operation.indexData = new Ogre::IndexData();
geometry->render_operation.indexData->indexStart = 0;
geometry->render_operation.indexData->indexCount = num_indices;
geometry->render_operation.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
// Set up the vertex declaration.
Ogre::VertexDeclaration* vertex_declaration = geometry->render_operation.vertexData->vertexDeclaration;
size_t element_offset = 0;
vertex_declaration->addElement(0, element_offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
element_offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
vertex_declaration->addElement(0, element_offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
element_offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
vertex_declaration->addElement(0, element_offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
#if GK_PLATFORM == GK_PLATFORM_APPLE_IOS
// Create the vertex buffer.
Ogre::HardwareVertexBufferSharedPtr vertex_buffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertex_declaration->getVertexSize(0), num_vertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,true);
geometry->render_operation.vertexData->vertexBufferBinding->setBinding(0, vertex_buffer);
// Fill the vertex buffer.
RocketOgre3DVertex* ogre_vertices = (RocketOgre3DVertex*) vertex_buffer->lock(0, vertex_buffer->getSizeInBytes(), Ogre::HardwareBuffer::HBL_DISCARD);
#else
Ogre::HardwareVertexBufferSharedPtr vertex_buffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertex_declaration->getVertexSize(0), num_vertices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
geometry->render_operation.vertexData->vertexBufferBinding->setBinding(0, vertex_buffer);
// Fill the vertex buffer.
RocketOgre3DVertex* ogre_vertices = (RocketOgre3DVertex*) vertex_buffer->lock(0, vertex_buffer->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL);
#endif
for (int i = 0; i < num_vertices; ++i)
{
ogre_vertices[i].x = vertices[i].position.x;
ogre_vertices[i].y = vertices[i].position.y;
ogre_vertices[i].z = 0;
Ogre::ColourValue diffuse(vertices[i].colour.red / 255.0f, vertices[i].colour.green / 255.0f, vertices[i].colour.blue / 255.0f, vertices[i].colour.alpha / 255.0f);
render_system->convertColourValue(diffuse, &ogre_vertices[i].diffuse);
ogre_vertices[i].u = vertices[i].tex_coord[0];
ogre_vertices[i].v = vertices[i].tex_coord[1];
}
vertex_buffer->unlock();
#if GK_PLATFORM == GK_PLATFORM_APPLE_IOS
// Create the index buffer.
Ogre::HardwareIndexBufferSharedPtr index_buffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, num_indices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
geometry->render_operation.indexData->indexBuffer = index_buffer;
geometry->render_operation.useIndexes = true;
#else
Ogre::HardwareIndexBufferSharedPtr index_buffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_32BIT, num_indices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
geometry->render_operation.indexData->indexBuffer = index_buffer;
geometry->render_operation.useIndexes = true;
#endif
// Fill the index buffer.
unsigned short * ogre_indices = (unsigned short*)index_buffer->lock(0, index_buffer->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL);
#if GK_PLATFORM == GK_PLATFORM_APPLE_IOS
//unsigned short short_indices[num_indices];
for(int i=0;i<num_indices;i++)
ogre_indices[i] = indices[i];
//memcpy(ogre_indices, short_indices, sizeof(unsigned short) * num_indices);
#else
memcpy(ogre_indices, indices, sizeof(unsigned int) * num_indices);
#endif
index_buffer->unlock();
return reinterpret_cast<Rocket::Core::CompiledGeometryHandle>(geometry);
}
// Called by Rocket when it wants to render application-compiled geometry.
void RenderInterfaceOgre3D::RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation)
{
Ogre::Matrix4 transform;
transform.makeTrans(translation.x, translation.y, 0);
render_system->_setWorldMatrix(transform);
render_system = Ogre::Root::getSingleton().getRenderSystem();
RocketOgre3DCompiledGeometry* ogre3d_geometry = (RocketOgre3DCompiledGeometry*) geometry;
if (ogre3d_geometry->texture != NULL)
{
render_system->_setTexture(0, true, ogre3d_geometry->texture->texture);
// Ogre can change the blending modes when textures are disabled - so in case the last render had no texture,
// we need to re-specify them.
render_system->_setTextureBlendMode(0, colour_blend_mode);
render_system->_setTextureBlendMode(0, alpha_blend_mode);
}
else
render_system->_disableTextureUnit(0);
render_system->_render(ogre3d_geometry->render_operation);
}