void PackedPatchTable::pack(Far::PatchTable* patch_table, int offset) { num_arrays = 0; num_patches = 0; num_indices = 0; num_nodes = 0; #ifdef WITH_OPENSUBDIV num_arrays = patch_table->GetNumPatchArrays(); for(int i = 0; i < num_arrays; i++) { int patches = patch_table->GetNumPatches(i); int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); num_patches += patches; num_indices += patches * num_control; } table.resize(total_size()); uint* data = table.data(); uint* array = data; uint* index = array + num_arrays * PATCH_ARRAY_SIZE; uint* param = index + num_indices; uint* handle = param + num_patches * PATCH_PARAM_SIZE; uint current_param = 0; for(int i = 0; i < num_arrays; i++) { *(array++) = patch_table->GetPatchArrayDescriptor(i).GetType(); *(array++) = patch_table->GetNumPatches(i); *(array++) = (index - data) + offset; *(array++) = (param - data) + offset; Far::ConstIndexArray indices = patch_table->GetPatchArrayVertices(i); for(int j = 0; j < indices.size(); j++) { *(index++) = indices[j]; } const Far::PatchParamTable& param_table = patch_table->GetPatchParamTable(); int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); int patches = patch_table->GetNumPatches(i); for(int j = 0; j < patches; j++, current_param++) { *(param++) = param_table[current_param].field0; *(param++) = param_table[current_param].field1; *(handle++) = (array - data) - PATCH_ARRAY_SIZE + offset; *(handle++) = (param - data) - PATCH_PARAM_SIZE + offset; *(handle++) = j * num_control; } } build_patch_map(*this, patch_table, offset); #else (void)patch_table; (void)offset; #endif }
CpuPatchTable::CpuPatchTable(const Far::PatchTable *farPatchTable) { int nPatchArrays = farPatchTable->GetNumPatchArrays(); // count int numPatches = 0; int numIndices = 0; for (int j = 0; j < nPatchArrays; ++j) { int nPatch = farPatchTable->GetNumPatches(j); int nCV = farPatchTable->GetPatchArrayDescriptor(j).GetNumControlVertices(); numPatches += nPatch; numIndices += nPatch * nCV; } _patchArrays.reserve(nPatchArrays); _indexBuffer.reserve(numIndices); _patchParamBuffer.reserve(numPatches); // for each patchArray for (int j = 0; j < nPatchArrays; ++j) { PatchArray patchArray(farPatchTable->GetPatchArrayDescriptor(j), farPatchTable->GetNumPatches(j), (int)_indexBuffer.size(), (int)_patchParamBuffer.size()); _patchArrays.push_back(patchArray); // indices Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j); for (int k = 0; k < indices.size(); ++k) { _indexBuffer.push_back(indices[k]); } // patchParams bundling // XXX: this process won't be needed if Far::PatchParam includes // sharpness. #if 0 // XXX: we need sharpness interface for patcharray or put sharpness // into patchParam. Far::ConstPatchParamArray patchParams = farPatchTable->GetPatchParams(j); for (int k = 0; k < patchParams.size(); ++k) { float sharpness = 0.0; _patchParamBuffer.push_back(patchParams[k].field0); _patchParamBuffer.push_back(patchParams[k].field1); _patchParamBuffer.push_back(*((unsigned int *)&sharpness)); } #else // XXX: workaround. GetPatchParamTable() will be deprecated though. Far::PatchParamTable const & patchParamTable = farPatchTable->GetPatchParamTable(); std::vector<Far::Index> const &sharpnessIndexTable = farPatchTable->GetSharpnessIndexTable(); int numPatches = farPatchTable->GetNumPatches(j); for (int k = 0; k < numPatches; ++k) { float sharpness = 0.0; int patchIndex = (int)_patchParamBuffer.size(); if (patchIndex < (int)sharpnessIndexTable.size()) { int sharpnessIndex = sharpnessIndexTable[patchIndex]; if (sharpnessIndex >= 0) sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex]; } PatchParam param; //param.patchParam = patchParamTable[patchIndex]; param.field0 = patchParamTable[patchIndex].field0; param.field1 = patchParamTable[patchIndex].field1; param.sharpness = sharpness; _patchParamBuffer.push_back(param); } #endif } }
//------------------------------------------------------------------------------ int main(int, char **) { // Generate some FarTopologyRefiner (see far_tutorial_0 for details). Far::TopologyRefiner * refiner = createTopologyRefiner(); // Uniformly refine the topolgy up to 'maxlevel'. int maxlevel = 4; refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel)); // Use the FarStencilTable factory to create cascading stencil table // note: we want stencils for the each refinement level // "cascade" mode is achieved by setting "factorizeIntermediateLevels" // to false Far::StencilTableFactory::Options options; options.generateIntermediateLevels=true; options.factorizeIntermediateLevels=false; options.generateOffsets=true; Far::StencilTable const * stencilTable = Far::StencilTableFactory::Create(*refiner, options); std::vector<Vertex> vertexBuffer(refiner->GetNumVerticesTotal()-g_nverts); Vertex * destVerts = &vertexBuffer[0]; int start = 0, end = 0; // stencils batches for each level of subdivision for (int level=0; level<maxlevel; ++level) { int nverts = refiner->GetLevel(level+1).GetNumVertices(); Vertex const * srcVerts = reinterpret_cast<Vertex *>(g_verts); if (level>0) { srcVerts = &vertexBuffer[start]; } start = end; end += nverts; stencilTable->UpdateValues(srcVerts, destVerts, start, end); // apply 2 hierarchical edits on level 1 vertices if (level==1) { float * pos = destVerts[start+5].GetPosition(); pos[1] += 0.5f; pos = destVerts[start+20].GetPosition(); pos[0] += 0.25f; } } { // Output OBJ of the highest level refined ----------- Vertex * verts = &vertexBuffer[0]; // Print vertex positions for (int level=1, firstvert=0; level<=maxlevel; ++level) { Far::TopologyLevel const & refLevel = refiner->GetLevel(level); printf("g level_%d\n", level); int nverts = refLevel.GetNumVertices(); for (int vert=0; vert<nverts; ++vert) { float const * pos = verts[vert].GetPosition(); printf("v %f %f %f\n", pos[0], pos[1], pos[2]); } verts += nverts; // Print faces for (int face=0; face<refLevel.GetNumFaces(); ++face) { Far::ConstIndexArray fverts = refLevel.GetFaceVertices(face); // all refined Catmark faces should be quads assert(fverts.size()==4); printf("f "); for (int vert=0; vert<fverts.size(); ++vert) { printf("%d ", fverts[vert]+firstvert+1); // OBJ uses 1-based arrays... } printf("\n"); } firstvert+=nverts; } } delete refiner; delete stencilTable; }
//------------------------------------------------------------------------------ int main(int, char **) { int maxlevel = 3; typedef Far::TopologyRefinerFactoryBase::TopologyDescriptor Descriptor; Sdc::SchemeType type = OpenSubdiv::Sdc::SCHEME_CATMARK; Sdc::Options options; options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY); options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_NONE); // Populate a topology descriptor with our raw data Descriptor desc; desc.numVertices = g_nverts; desc.numFaces = g_nfaces; desc.numVertsPerFace = g_vertsperface; desc.vertIndicesPerFace = g_vertIndices; // Create a face-varying channel descriptor Descriptor::FVarChannel uvs; uvs.numValues = g_nuvs; uvs.valueIndices = g_uvIndices; // Add the channel topology to the main descriptor desc.numFVarChannels = 1; desc.fvarChannels = & uvs; // Instantiate a FarTopologyRefiner from the descriptor Far::TopologyRefiner * refiner = Far::TopologyRefinerFactory<Descriptor>::Create(desc, Far::TopologyRefinerFactory<Descriptor>::Options(type, options)); // Uniformly refine the topolgy up to 'maxlevel' // note: fullTopologyInLastLevel must be true to work with face-varying data { Far::TopologyRefiner::UniformOptions options(maxlevel); options.fullTopologyInLastLevel = true; refiner->RefineUniform(options); } // Allocate & interpolate the 'vertex' primvar data (see tutorial 2 for // more details). std::vector<Vertex> vbuffer(refiner->GetNumVerticesTotal()); Vertex * verts = &vbuffer[0]; int nCoarseVerts = g_nverts; for (int i=0; i<nCoarseVerts; ++i) { verts[i].SetPosition(g_verts[i][0], g_verts[i][1], g_verts[i][2]); } refiner->Interpolate(verts, verts + nCoarseVerts); // Allocate & interpolate the 'face-varying' primvar data int channel = 0, nCoarseFVVerts = refiner->GetNumFVarValues(0, channel); std::vector<FVarVertex> fvBuffer(refiner->GetNumFVarValuesTotal(channel)); FVarVertex * fvVerts = &fvBuffer[0]; for (int i=0; i<g_nuvs; ++i) { fvVerts[i].u = g_uvs[i][0]; fvVerts[i].v = g_uvs[i][1]; } refiner->InterpolateFaceVarying(fvVerts, fvVerts + nCoarseFVVerts, channel); { // Output OBJ of the highest level refined ----------- // Print vertex positions for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { for (int vert=0; vert<refiner->GetNumVertices(level); ++vert) { float const * pos = verts[firstVert+vert].GetPosition(); printf("v %f %f %f\n", pos[0], pos[1], pos[2]); } } else { firstVert += refiner->GetNumVertices(level); } } // Print uvs for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { for (int vert=0; vert<refiner->GetNumFVarValues(level, channel); ++vert) { FVarVertex const & uv = fvVerts[firstVert+vert]; printf("vt %f %f\n", uv.u, uv.v); } } else { firstVert += refiner->GetNumFVarValues(level, channel); } } // Print faces for (int face=0; face<refiner->GetNumFaces(maxlevel); ++face) { Far::ConstIndexArray fverts = refiner->GetFaceVertices(maxlevel, face), fvverts = refiner->GetFVarFaceValues(maxlevel, face, channel); // all refined Catmark faces should be quads assert(fverts.size()==4 and fvverts.size()==4); printf("f "); for (int vert=0; vert<fverts.size(); ++vert) { // OBJ uses 1-based arrays... printf("%d/%d ", fverts[vert]+1, fvverts[vert]+1); } printf("\n"); } } }