bool OsdUtilAdaptiveEvaluator::Refine( int numThreads, string * /* errorMessage */) { const FarMesh<OsdVertex> *fmesh = _refiner->GetFarMesh(); if (numThreads > 1) { #ifdef OPENSUBDIV_HAS_OPENMP OsdOmpComputeController ompComputeController(numThreads); ompComputeController.Refine(_computeContext, fmesh->GetKernelBatches(), _vertexBuffer, _vvBuffer); return true; #endif } OsdCpuComputeController cpuComputeController; cpuComputeController.Refine(_computeContext, fmesh->GetKernelBatches(), _vertexBuffer, _vvBuffer); return true; }
//------------------------------------------------------------------------------ static void createOsdMesh( const std::string &shape, int level, Scheme scheme=kCatmark ) { // Create HBR mesh OsdHbrMesh * hmesh = simpleHbr<OsdVertex>(shape.c_str(), scheme, g_orgPositions, true); g_positions.resize(g_orgPositions.size(),0.0f); int nfaces = hmesh->GetNumFaces(), nptexfaces = getNumPtexFaces(hmesh, nfaces); // Generate sample locations int nsamples = createRandomSamples( nptexfaces, g_nsamples, g_coords ); createCoarseMesh(hmesh, nfaces); // Create FAR mesh OsdFarMeshFactory factory( hmesh, level, /*adaptive*/ true); delete g_fmesh; g_fmesh = factory.Create(/*fvar*/ true); int nverts = g_fmesh->GetNumVertices(); // Create v-buffer & populate w/ positions delete g_vertexData; g_vertexData = OsdCpuVertexBuffer::Create(3, nverts); // Create primvar v-buffer & populate w/ colors or (u,v) data delete g_varyingData; g_varyingData = 0; if (g_drawMode==kVARYING) { g_varyingData = OsdCpuVertexBuffer::Create(3, nverts); g_varyingData->UpdateData( &g_varyingColors[0], 0, nverts); } // Create a Compute context, used to "pose" the vertices delete g_computeCtx; g_computeCtx = OsdCpuComputeContext::Create(g_fmesh->GetSubdivisionTables(), g_fmesh->GetVertexEditTables()); g_computeCtrl.Refine( g_computeCtx, g_fmesh->GetKernelBatches(), g_vertexData, g_varyingData ); // Create eval context & data buffers delete g_evalCtx; g_evalCtx = OsdCpuEvalLimitContext::Create(g_fmesh->GetPatchTables(), /*requireFVarData*/ true); delete g_Q; g_Q = OsdCpuGLVertexBuffer::Create(6,nsamples); memset( g_Q->BindCpuBuffer(), 0, nsamples*6*sizeof(float)); delete g_dQu; g_dQu = OsdCpuGLVertexBuffer::Create(6,nsamples); memset( g_dQu->BindCpuBuffer(), 0, nsamples*6*sizeof(float)); delete g_dQv; g_dQv = OsdCpuGLVertexBuffer::Create(6,nsamples); memset( g_dQv->BindCpuBuffer(), 0, nsamples*6*sizeof(float)); updateGeom(); // Bind g_Q as a GL_POINTS VBO glBindVertexArray(g_samplesVAO); glBindBuffer(GL_ARRAY_BUFFER, g_Q->BindVBO()); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12); glBindVertexArray(0); }
//------------------------------------------------------------------------------ static void updateGeom() { int nverts = (int)g_orgPositions.size() / 3; const float *p = &g_orgPositions[0]; float r = sin(g_frame*0.001f) * g_moveScale; for (int i = 0; i < nverts; ++i) { //float move = 0.05f*cosf(p[0]*20+g_frame*0.01f); float ct = cos(p[2] * r); float st = sin(p[2] * r); g_positions[i*3+0] = p[0]*ct + p[1]*st; g_positions[i*3+1] = -p[0]*st + p[1]*ct; g_positions[i*3+2] = p[2]; p+=3; } // Run Compute pass to pose the control vertices --------------------------- Stopwatch s; s.Start(); g_vertexData->UpdateData( &g_positions[0], 0, nverts); g_computeCtrl.Refine( g_computeCtx, g_fmesh->GetKernelBatches(), g_vertexData, g_varyingData ); s.Stop(); g_computeTime = float(s.GetElapsed() * 1000.0f); // Run Eval pass to get the samples locations ------------------------------ s.Start(); // Reset the output buffer g_nsamplesFound=0; // Bind/Unbind of the vertex buffers to the context needs to happen // outside of the parallel loop g_evalCtx->GetVertexData().Bind( g_idesc, g_vertexData, g_odesc, g_Q, g_dQu, g_dQv ); // The varying data ends-up interleaved in the same g_Q output buffer because // g_Q has a stride of 6 and g_vdesc sets the offset to 3, while g_odesc sets // the offset to 0 switch (g_drawMode) { case kVARYING : g_evalCtx->GetVaryingData().Bind( g_idesc, g_varyingData, g_vdesc, g_Q ); break; case kFACEVARYING : g_evalCtx->GetFaceVaryingData().Bind( g_fvidesc, g_fvodesc, g_Q ); case kUV : default : g_evalCtx->GetVaryingData().Unbind(); break; } #define USE_OPENMP #if defined(OPENSUBDIV_HAS_OPENMP) and defined(USE_OPENMP) #pragma omp parallel for #endif for (int i=0; i<(int)g_coords.size(); ++i) { int n = g_evalCtrl.EvalLimitSample<OsdCpuVertexBuffer,OsdCpuGLVertexBuffer>( g_coords[i], g_evalCtx, i ); if (n) { // point colors switch (g_drawMode) { case kUV : { float * color = g_Q->BindCpuBuffer() + i*g_Q->GetNumElements() + 3; color[0] = g_coords[i].u; color[1] = 0.0f; color[2] = g_coords[i].v; } break; case kVARYING : break; case kFACEVARYING : break; default : break; } #if defined(OPENSUBDIV_HAS_OPENMP) and defined(USE_OPENMP) #pragma omp atomic #endif g_nsamplesFound += n; } else { // "hide" unfound samples (hole tags...) as a black dot at the origin float * sample = g_Q->BindCpuBuffer() + i*g_Q->GetNumElements(); memset(sample, 0, g_Q->GetNumElements() * sizeof(float)); } } g_evalCtx->GetVertexData().Unbind(); switch (g_drawMode) { case kVARYING : g_evalCtx->GetVaryingData().Unbind(); break; case kFACEVARYING : g_evalCtx->GetFaceVaryingData().Unbind(); break; default : break; } g_Q->BindVBO(); s.Stop(); g_evalTime = float(s.GetElapsed() * 1000.0f); }