OBJScene::Texture *loadPtexTexture(const FileName& filename) { #if defined(USE_PTEX) std::string fn = filename.str(); Ptex::String error; std::cout << "opening " << fn << " ... " << std::flush; PtexTexture* tex = PtexTexture::open(fn.c_str(),error); if (!tex) { std::cout << "[FAILED]" << std::endl; THROW_RUNTIME_ERROR("cannot open ptex file: "+fn); } PtexMetaData *metadata = tex->getMetaData(); const int32_t *vertices_per_face = nullptr; int geom_faces = 0; metadata->getValue("PtexFaceVertCounts", vertices_per_face, geom_faces); OBJScene::Texture **face_textures = new OBJScene::Texture *[geom_faces]; for (size_t i=0;i<geom_faces;i++) face_textures[i] = nullptr; OBJScene::Texture *texture = new OBJScene::Texture(); texture->width = 0; texture->height = 0; texture->format = OBJScene::Texture::PTEX_RGBA8; texture->faceTextures = geom_faces; texture->data = face_textures; texture->width_mask = 0; texture->height_mask = 0; int nchan = tex->numChannels(); if (nchan != 3 && nchan != 1) { std::cout << "[FAILED]" << std::endl; THROW_RUNTIME_ERROR(fn+": ptex file with other than 1 or 3 channels found!"); } if (nchan == 1) texture->format = OBJScene::Texture::PTEX_FLOAT32; float px[3]; int ptex_face_id = 0; for (size_t geom_face_id=0;geom_face_id<geom_faces;geom_face_id++) { face_textures[geom_face_id] = nullptr; const Ptex::FaceInfo &fi = tex->getFaceInfo(ptex_face_id); int n = vertices_per_face[geom_face_id]; if (n == 4) /* ptex data only for quads */ { Ptex::Res res = fi.res; OBJScene::Texture *face_txt = new OBJScene::Texture(); face_txt->width = res.u(); face_txt->height = res.v(); face_txt->width_mask = 0; face_txt->height_mask = 0; face_txt->data = nullptr; face_textures[geom_face_id] = face_txt; if (nchan == 3) /* rgb color data */ { face_txt->format = OBJScene::Texture::RGBA8; face_txt->bytesPerTexel = 4; unsigned char *data = new unsigned char[face_txt->bytesPerTexel*face_txt->width*face_txt->height]; face_txt->data = data; for (int vi = 0; vi < face_txt->height; vi++) { for (int ui = 0; ui < face_txt->width; ui++) { tex->getPixel(ptex_face_id, ui, vi, px, 0, nchan, res); data[(vi*face_txt->width+ui)*4+0] = (unsigned char)(px[0]*255.0f); data[(vi*face_txt->width+ui)*4+1] = (unsigned char)(px[1]*255.0f); data[(vi*face_txt->width+ui)*4+2] = (unsigned char)(px[2]*255.0f); } } } else if (nchan == 1) /* displacement data */ { face_txt->format = OBJScene::Texture::FLOAT32; face_txt->bytesPerTexel = 4; float*data = new float[face_txt->width*face_txt->height]; face_txt->data = data; for (int vi = 0; vi < face_txt->height; vi++) { for (int ui = 0; ui < face_txt->width; ui++) { tex->getPixel(ptex_face_id, ui, vi, px, 0, nchan, res); if (!isfinite(px[0])) px[0] = 0.0f; data[vi*face_txt->width+ui] = px[0]; } } } ptex_face_id++; } else ptex_face_id += 3; } std::cout << "done" << std::endl << std::flush; return texture; #else return nullptr; #endif }
bool mesh::loadFromMetaData(PtexTexture* r) { PtexMetaData* meta = r->getMetaData(); if (meta->numKeys()<3) return false; triangles = r->meshType()==Ptex::mt_triangle; const float* vf; const int *vif, *fvc; int vertcount, indexcount, facevertcount; meta->getValue("PtexFaceVertCounts",fvc,facevertcount); if (facevertcount==0) return false; meta->getValue("PtexVertPositions",vf,vertcount); if (vertcount==0) return false; meta->getValue("PtexFaceVertIndices",vif,indexcount); if (indexcount==0) return false; for (int i=0; i<vertcount; i+=3) addVertex(&vf[i]); int* fviptr = (int*) vif; int* nvptr = (int*) fvc; for (int i=0; i<facevertcount; i++) { int nverts = *nvptr; if (triangles) { if (nverts!=3) return false; polygon q; q.indices[0] = fviptr[0]; q.indices[1] = fviptr[1]; q.indices[2] = fviptr[2]; q.indices[3] = -1; addFace(q); } else if (nverts==4) { polygon q; q.indices[0] = fviptr[0]; q.indices[1] = fviptr[1]; q.indices[2] = fviptr[2]; q.indices[3] = fviptr[3]; addFace(q); } else { int vib = verts.size(); // Add new vertices at edge midpoints and polygon center Vec3f cp = Vec3f(0,0,0); for (int v=0; v<nverts; v++) { verts.push_back((verts[fviptr[v]] + verts[fviptr[(v+1)%nverts]])/2); cp += verts[fviptr[v]]; } verts.push_back(cp/nverts); // Add the new sub-faces for (int v=0; v<nverts; v++) { polygon q; q.indices[0] = fviptr[v]; q.indices[1] = vib+v; q.indices[2] = verts.size()-1; q.indices[3] = vib+(v+nverts-1)%nverts; addFace(q); } } fviptr+=nverts; nvptr++; } if ((int)polys.size()!=r->numFaces()) { verts.clear(); polys.clear(); return false; } return true; }
OpenSubdiv::HbrMesh<T> * createPTexGeo(PtexTexture * r) { PtexMetaData* meta = r->getMetaData(); if(meta->numKeys()<3) return NULL; const float* vp; const int *vi, *vc; int nvp, nvi, nvc; meta->getValue("PtexFaceVertCounts", vc, nvc); if (nvc==0) return NULL; meta->getValue("PtexVertPositions", vp, nvp); if (nvp==0) return NULL; meta->getValue("PtexFaceVertIndices", vi, nvi); if (nvi==0) return NULL; static OpenSubdiv::HbrCatmarkSubdivision<T> _catmark; static OpenSubdiv::HbrBilinearSubdivision<T> _bilinear; OpenSubdiv::HbrMesh<T> * mesh; if(g_scheme == 0) mesh = new OpenSubdiv::HbrMesh<T>(&_catmark); else mesh = new OpenSubdiv::HbrMesh<T>(&_bilinear); g_positions.clear(); g_positions.reserve(nvp); // compute model bounding float min[3] = {vp[0], vp[1], vp[2]}; float max[3] = {vp[0], vp[1], vp[2]}; for (int i=0; i<nvp/3; ++i) { for(int j=0; j<3; ++j) { float v = vp[i*3+j]; g_positions.push_back(v); min[j] = std::min(min[j], v); max[j] = std::max(max[j], v); } mesh->NewVertex(i, T()); } for (int j=0; j<3; ++j) { g_center[j] = (min[j] + max[j]) * 0.5f; g_size += (max[j]-min[j])*(max[j]-min[j]); } g_size = sqrtf(g_size); const int *fv = vi; for (int i=0, ptxidx=0; i<nvc; ++i) { int nv = vc[i]; OpenSubdiv::HbrFace<T> * face = mesh->NewFace(nv, (int *)fv, 0); face->SetPtexIndex(ptxidx); if(nv != 4) ptxidx+=nv; else ptxidx++; fv += nv; } mesh->SetInterpolateBoundaryMethod( OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeOnly ); // set creases here // applyTags<T>( mesh, sh ); mesh->Finish(); return mesh; }