nuiRect nuiPathGenerator::GetRect() { float minx = 0, maxx = 0; float miny = 0, maxy = 0; bool first = true; nuiPath points; Tessellate(points, 0.01f); for (uint32 i = 0; i < points.GetCount(); i++) { const nuiPoint& rP = points[i]; float x = rP.Elt[0]; float y = rP.Elt[1]; if (!first) { minx = MIN(minx,x); maxx = MAX(maxx,x); miny = MIN(miny,y); maxy = MAX(maxy,y); } else { minx = maxx = x; miny = maxy = y; first = false; } } return nuiRect(minx, miny, maxx, maxy, false); }
bool nuiOutliner::Tessellate(nuiPath& rPoints, float Quality) const { nuiPath Vertices; bool res = mpPath->Tessellate(Vertices, Quality); rPoints.Clear(); if (!res) return false; uint total = Vertices.GetCount(); uint offset = 0; uint count = total; //Find sub path: for (uint i = offset; i < total; i++) { uint ii = i+1; if (Vertices[i].GetType() == nuiPointTypeStop || ii == total) { count = ii - offset; if (Vertices[i].GetType() == nuiPointTypeStop) count--; Tessellate(rPoints, Vertices, offset, count, Quality); offset = ii; } } return res; }
//************************************************************************************************************* void Event_KeyUp(unsigned char keycode) { int numcurves = sizeof(curves) / sizeof(curves[0]); for( int i = 0; i < numcurves; ++i ) { if( keycode == 0x31 + i ) { ChangeCurve(i); Tessellate(); } } switch( keycode ) { case 0x46: fullscreen = !fullscreen; break; case 0x55: break; case 0x57: wireframe = !wireframe; break; case VK_ADD: numsegments = GLMin<GLuint>(numsegments + 10, MAX_NUM_SEGMENTS); Tessellate(); break; case VK_SUBTRACT: numsegments = GLMax<GLuint>(numsegments - 10, 10); Tessellate(); break; default: break; } }
//************************************************************************************************************* void Event_MouseMove(int x, int y, short dx, short dy) { mousex = x; mousey = y; mousedx += dx; mousedy += dy; if( mousedown == 1 ) { if( !fullscreen ) { if( UpdateControlPoints((float)mousex, (float)mousey) ) Tessellate(); } } else selectedcontrolpoint = -1; }
bool InitScene() { SurfaceVertex* svdata = 0; float (*vdata)[4] = 0; GLushort* idata = 0; GLuint* idata32 = 0; OpenGLVertexElement decl[] = { { 0, 0, GLDECLTYPE_FLOAT4, GLDECLUSAGE_POSITION, 0 }, { 0xff, 0, 0, 0, 0 } }; OpenGLVertexElement decl2[] = { { 0, 0, GLDECLTYPE_FLOAT4, GLDECLUSAGE_POSITION, 0 }, { 0, 16, GLDECLTYPE_FLOAT4, GLDECLUSAGE_NORMAL, 0 }, { 0xff, 0, 0, 0, 0 } }; SetWindowText(hwnd, TITLE); Quadron::qGLExtensions::QueryFeatures(hdc); // calculate viewport sizes long maxw = screenwidth - 350; // assume 320x240 first long maxh = screenheight - 130 - 10; // text is fix splinevpsize = GLMin<long>(maxw, maxh); splinevpsize -= (splinevpsize % 10); surfvpwidth = screenwidth - splinevpsize - 30; surfvpheight = (surfvpwidth * 3) / 4; if( !Quadron::qGLExtensions::ARB_geometry_shader4 ) return false; hascompute = Quadron::qGLExtensions::ARB_compute_shader; #ifdef _DEBUG if( Quadron::qGLExtensions::ARB_debug_output ) { glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); glDebugMessageCallback(ReportGLError, 0); } #endif glClearColor(0.0f, 0.125f, 0.3f, 1.0f); glClearDepth(1.0); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); // create grid & control poly if( !GLCreateMesh(44 + numcontrolvertices, numcontrolindices, GLMESH_DYNAMIC, decl, &supportlines) ) { MYERROR("Could not create mesh"); return false; } supportlines->LockVertexBuffer(0, 0, GLLOCK_DISCARD, (void**)&vdata); supportlines->LockIndexBuffer(0, 0, GLLOCK_DISCARD, (void**)&idata); // grid points for( GLuint i = 0; i < 22; i += 2 ) { vdata[i][0] = vdata[i + 1][0] = (float)(i / 2); vdata[i][2] = vdata[i + 1][2] = 0; vdata[i][3] = vdata[i + 1][3] = 1; vdata[i][1] = 0; vdata[i + 1][1] = 10; vdata[i + 22][1] = vdata[i + 23][1] = (float)(i / 2); vdata[i + 22][2] = vdata[i + 23][2] = 0; vdata[i + 22][3] = vdata[i + 23][3] = 1; vdata[i + 22][0] = 0; vdata[i + 23][0] = 10; } // curve indices for( GLuint i = 0; i < numcontrolindices; i += 2 ) { idata[i] = 44 + i / 2; idata[i + 1] = 44 + i / 2 + 1; } supportlines->UnlockIndexBuffer(); supportlines->UnlockVertexBuffer(); OpenGLAttributeRange table[] = { { GLPT_LINELIST, 0, 0, 0, 0, 44 }, { GLPT_LINELIST, 1, 0, numcontrolindices, 44, numcontrolvertices } }; supportlines->SetAttributeTable(table, 2); // create spline mesh if( !GLCreateMesh(maxsplinevertices, maxsplineindices, GLMESH_32BIT, decl, &curve) ) { MYERROR("Could not create curve"); return false; } OpenGLAttributeRange* subset0 = curve->GetAttributeTable(); subset0->PrimitiveType = GLPT_LINELIST; subset0->IndexCount = 0; // create surface if( !GLCreateMesh(maxsurfacevertices, maxsurfaceindices, GLMESH_32BIT, decl2, &surface) ) { MYERROR("Could not create surface"); return false; } // load effects if( !GLCreateEffectFromFile("../media/shadersGL/color.vert", "../media/shadersGL/renderpoints.geom", "../media/shadersGL/color.frag", &renderpoints) ) { MYERROR("Could not load point renderer shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/color.vert", "../media/shadersGL/renderlines.geom", "../media/shadersGL/color.frag", &renderlines) ) { MYERROR("Could not load line renderer shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/rendersurface.vert", 0, "../media/shadersGL/rendersurface.frag", &rendersurface) ) { MYERROR("Could not load surface renderer shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/basic2D.frag", &basic2D) ) { MYERROR("Could not load basic 2D shader"); return false; } if( hascompute ) { if( !GLCreateComputeProgramFromFile("../media/shadersGL/tessellatecurve.comp", &tessellatecurve) ) { MYERROR("Could not load compute shader"); return false; } if( !GLCreateComputeProgramFromFile("../media/shadersGL/tessellatesurface.comp", &tessellatesurface) ) { MYERROR("Could not load compute shader"); return false; } } screenquad = new OpenGLScreenQuad(); // tessellate for the first time ChangeCurve(0); Tessellate(); // text GLCreateTexture(800, 130, 1, GLFMT_A8R8G8B8, &text1); UpdateText(); float angles[2] = { M_PI / 2, 0.5f }; cameraangle = angles; return true; }
/** * Retessellates the current terrain */ void CRoamMeshDrawer::Update() { //FIXME this retessellates with the current camera frustum, shadow pass and others don't have to see the same patches! //const CCamera* cam = (inShadowPass)? camera: cam2; CCamera* cam = cam2; // Update Patch visibility Patch::UpdateVisibility(cam, m_Patches, numPatchesX); // Check if a retessellation is needed #define RETESSELLATE_MODE 1 bool retessellate = false; { //SCOPED_TIMER("ROAM::ComputeVariance"); for (int i = 0; i < (numPatchesX * numPatchesY); ++i) { Patch& p = m_Patches[i]; #if (RETESSELLATE_MODE == 2) if (p.IsVisible()) { if (!visibilitygrid[i]) { visibilitygrid[i] = true; retessellate = true; } if (p.IsDirty()) { //FIXME don't retessellate on small heightmap changes? p.ComputeVariance(); retessellate = true; } } else { visibilitygrid[i] = false; } #else if (p.IsVisible() != visibilitygrid[i]) { visibilitygrid[i] = p.IsVisible(); retessellate = true; } if (p.IsVisible() && p.IsDirty()) { //FIXME don't retessellate on small heightmap changes? p.ComputeVariance(); retessellate = true; } #endif } } // Further conditions that can cause a retessellation #if (RETESSELLATE_MODE == 2) static const float maxCamDeltaDistSq = 500.0f * 500.0f; retessellate |= ((cam->pos - lastCamPos).SqLength() > maxCamDeltaDistSq); #endif retessellate |= forceRetessellate; retessellate |= (lastGroundDetail != smfGroundDrawer->GetGroundDetail()); // Retessellate if (retessellate) { { //SCOPED_TIMER("ROAM::Tessellate"); //FIXME this tessellates with current camera + viewRadius // so it doesn't retessellate patches that are e.g. only vis. in the shadow frustum Reset(); Tessellate(cam->pos, smfGroundDrawer->GetGroundDetail()); } { //SCOPED_TIMER("ROAM::GenerateIndexArray"); #pragma omp parallel for for (int i = m_Patches.size() - 1; i >= 0; --i) { Patch* it = &m_Patches[i]; if (it->IsVisible()) { it->GenerateIndices(); } } } { //SCOPED_TIMER("ROAM::Upload"); for (std::vector<Patch>::iterator it = m_Patches.begin(); it != m_Patches.end(); ++it) { if (it->IsVisible()) { it->Upload(); } } } /*{ int tricount = 0; for (std::vector<Patch>::iterator it = m_Patches.begin(); it != m_Patches.end(); it++) { if (it->IsVisible()) { tricount += it->GetTriCount(); } } LOG_L(L_DEBUG, "ROAM dbg: Framechange, fram=%i tris=%i, viewrad=%i, cd=%f, camera=(%5.0f, %5.0f, %5.0f) camera2= (%5.0f, %5.0f, %5.0f)", globalRendering->drawFrame, tricount, smfGroundDrawer->viewRadius, (cam->pos - lastCamPos).SqLength();, camera->pos.x, camera->pos.y, camera->pos.z, cam2->pos.x, cam2->pos.y, cam2->pos.z ); }*/ lastGroundDetail = smfGroundDrawer->GetGroundDetail(); lastCamPos = cam->pos; forceRetessellate = false; } }