multithreading - C++ OpenGL Threading (Terrain) -


so, after long time got quadtree terrain working. means terrain far away less resolution terrain closer me. shown in picture - enter image description here

now, have many new problems... of them i've had many ideas on. there's ripping in between resolutions, texture size difference , above all... lag. due how determine if character standing in quad. using distance can make clean area around character , minimize ripping. causes lag due fact have check distance on recursively. first check parent, if that's within 100m split it. check it's children , it's children , children etc etc...

to fix this... decided it's time use threading. made rendering go different thread. in hope of reducing lag. however, have new problems. when terrain splits. vertex data changed.

void quadtree::setup(std::vector<glm::vec3> vertexdata, int width, int height) { center = glm::vec3((left+right)/2, 1, (top+down)/2); float previvalue; float prevjvalue; float ivalue; float jvalue; size = 25; w = 16 ; h = 16 ; id = 0;  for(int = 0; < w; i++)   {       for(int j = 0; j < h; j++)       {           ivalue = i;           jvalue = j;           //ivalue = * (pow(0.5, 2));          // jvalue = j * (pow(0.5, 2));               vertices.push_back(glm::vec3(0.0+ivalue, 1.0+id, 0.0+jvalue)); //top left           vertices.push_back(glm::vec3(0.0+ivalue, 1.0+id, 1.0+jvalue)); // bottom left           vertices.push_back(glm::vec3(1.0+ivalue, 1.0+id, 0.0+jvalue)); // top right            vertices.push_back(glm::vec3(1.0+ivalue, 1.0+id, 1.0+jvalue));           vertices.push_back(glm::vec3(1.0+ivalue, 1.0+id, 0.0+jvalue));           vertices.push_back(glm::vec3(0.0+ivalue, 1.0+id, 1.0+jvalue));        }   }  for(int = 0; < vertices.size(); i++) {      uvs.push_back(glm::vec2(vertices[i].x, vertices[i].z));      normals.push_back(vertices[i]);     glm::vec3 oldvec = vertices[i];     //glm::vec3 newvec = glm::normalize(oldvec);     //glm::vec3 newvec = oldvec * glm::vec3(size*(pow(0.5, level)), size, size*(pow(0.5, level)));       //newvec = newvec - glm::vec3(size*(pow(0.5, level)), size, size*(pow(0.5, level)));     /*     if(level != 1)     {         glm::vec3 translate = glm::vec3(50/(level-1), 0, 50/(level-1));         newvec = newvec - translate;     }else{         glm::vec3 translate = glm::vec3(50, 0, 50);         newvec = newvec - translate;     }     */     //glm::vec3 newvec = oldvec /  glm::vec3(2 ^ level, 1, 2 ^ level);       glm::vec3 newvec = oldvec * glm::vec3(size*(pow(0.5001, level)), size, size*(pow(0.5001, level)));      vertices[i] = newvec + glm::vec3(left, 0, top); //+ (glm::vec3(center.x - (100 * (1/(pow(abs(level-1),2)))), 1, center.z - (100 * (1/(pow(abs(level-1),2)))) ));        //std::cout << " x = " << (glm::vec3(center.x - (100 * (1/(pow(abs(level-1),2)))), 1, center.z - (100 * (1/(pow(abs(level-1),2)))) )).x << " z = " << (glm::vec3(center.x - (100 * (1/(pow(abs(level-1),2)))), 1, center.z - (100 * (1/(pow(abs(level-1),2)))) )).z << std::endl;  } for(int = 0; < vertices.size(); i+=3) {        // 3 vertices make faces       glm::vec3 p1 = vertices[i+0];       glm::vec3 p2 = vertices[i+1];       glm::vec3 p3 = vertices[i+2];        glm::vec3 v1 = p2 - p1;       glm::vec3 v2 = p3 - p1;       glm::vec3 normal = glm::cross( v1,v2 );        normal = glm::normalize(normal);        normals[i+0] = normal;       normals[i+1] = normal;       normals[i+2] = normal;  }  // std::cout << "terrain has: " << vertices.size() * 3 << " vertices!" << std::endl;     glgenbuffers(1, &vertexbuffer); glgenbuffers(1, &uvbuffer); glgenbuffers(1, &normalbuffer);  glbindbuffer(gl_array_buffer, vertexbuffer); glbufferdata(gl_array_buffer, vertices.size() * sizeof(glm::vec3), &vertices[0], gl_static_draw);  glbindbuffer(gl_array_buffer, normalbuffer); glbufferdata(gl_array_buffer, normals.size() * sizeof(glm::vec3), &normals[0], gl_static_draw);  glbindbuffer(gl_array_buffer, uvbuffer); glbufferdata(gl_array_buffer, uvs.size() * sizeof(glm::vec2), &uvs[0], gl_static_draw);  } 

and code executed in render thread -

void quadtree::render() {  if(isleaf) { //  std::cout << "rendering: " << id << std::endl;     //vertices      glenablevertexattribarray(0);     glbindbuffer(gl_array_buffer, vertexbuffer);     glvertexattribpointer(        0,                          3,                          gl_float,                   gl_false,                   0,                          (char*)0                );       //uvs      glenablevertexattribarray(1);      glbindbuffer(gl_array_buffer, uvbuffer);      glvertexattribpointer(        1,                                // attribute        2,                                // size        gl_float,                         // type        gl_false,                         // normalized?        0,                                // stride        (char*)0                          // array buffer offset      );       //normal      glenablevertexattribarray(2);      glbindbuffer(gl_array_buffer, normalbuffer);      glvertexattribpointer(        2,                                // attribute        3,                                // size        gl_float,                         // type        gl_false,                         // normalized?        0,                                // stride        (void*)0                          // array buffer offset      );       gldrawarrays(gl_triangles, 0, vertices.size() );      gldisablevertexattribarray(0);     gldisablevertexattribarray(1);     gldisablevertexattribarray(2);  } 

this happens if terrain split during rendering - enter image description here

i've heard things using mutex lock buffer hasn't seemed when tried it. can recommend can make work? rips great i'll open thread that. sorry length of question.

instead of filling vector vertices, should generate vector indices. if you're clever can use quadtree indexing mechanism: each quadtree subdivision adds bit in either direction. @ each level i,j index of quad series of left/right-top/bottom bits used reach leaf in tree.

another suggestion: don't try "morph" terrain. did in first quadtree engine , looks weird. instead should identify nodes in tree on lod border , render them twice, 1 time low lod, high lod , alpha blending between them. looks much, nicer.


on related note: 10 years ago, instead of cramming 1 of high school finals wrote small quadtree based terrain renderer instead. it's quite ugly code imho, example neither uses vertex arrays or other optimizations. in fact uses slow , inefficient immediate mode. "discovered" code on 1 of old hdds , added codesamples repository: https://github.com/datenwolf/codesamples/tree/master/samples/opengl/qt_terr

i think (quick , dirty, lacks proper error handling) parser terragen files worth more rest ;)


Comments

Popular posts from this blog

javascript - DIV "hiding" when changing dropdown value -

Does Firefox offer AppleScript support to get URL of windows? -

android - How to install packaged app on Firefox for mobile? -