OpenSubdiv::OsdGLPtexTexture * OpenSubdivPtexShader::loadPtex(const MString &filename) { if (filename.length()) { printf("Load ptex %s\n", filename.asChar()); Ptex::String ptexError; PtexTexture *ptex = PtexTexture::open(filename.asChar(), ptexError, true); if (ptex) { // create osdptex OpenSubdiv::OsdGLPtexTexture *osdptex = OpenSubdiv::OsdGLPtexTexture::Create(ptex, 0, /*gutterWidth=*/1, /*pageMargin=*/8); ptex->release(); return osdptex; } printf("Load ptex failed on file: \"%s\"\n", filename.asChar()); } return NULL; }
bool readEnvcube(const std::string& path, Img images[6]) { std::string error; PtexTexture* ptx = PtexTexture::open(path.c_str(), error); if (!ptx) { std::cerr << error << std::endl; return 0; } if (ptx->numFaces() != 6) { std::cerr << "Error: Ptex envcube file doesn't have six faces: "<< path << "\n"; ptx->release(); return 0; } bool ok; for (int i = 0; i < 6; i++) { ok = PtexToImg(ptx, images[i], /*faceid*/ i, /*flip*/ false); if (!ok) break; } ptx->release(); return ok; }
bool readImage(const std::string& path, Img& img) { if (endsWith(path, ".ptx")) { img.path = path; // read ptx face-zero image std::string error; PtexTexture* ptx = PtexTexture::open(path.c_str(), error); if (!ptx) { std::cerr << error << std::endl; return 0; } if (ptx->numFaces() != 1) { std::cerr << "Error: Ptex file has multiple faces (not yet supported)" << std::endl; ptx->release(); return 0; } bool ok = PtexToImg(ptx, img, /*faceid*/ 0, /*flip*/ true); ptx->release(); return ok; } else { return img.load(path); } }
bool PtexWriter::applyEdits(const char* path, Ptex::String& error) { // open reader for existing file PtexTexture* tex = PtexTexture::open(path, error); if (!tex) return 0; // see if we have any edits to apply if (tex->hasEdits()) { // create non-incremental writer PtexWriter* w = new PtexMainWriter(path, tex, tex->meshType(), tex->dataType(), tex->numChannels(), tex->alphaChannel(), tex->numFaces(), tex->hasMipMaps()); // close to rebuild file if (!w->close(error)) return 0; w->release(); } return 1; }
PtexWriter* PtexWriter::edit(const char* path, bool incremental, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces, Ptex::String& error, bool genmipmaps) { if (!checkFormat(mt, dt, nchannels, alphachan, error)) return 0; // try to open existing file (it might not exist) FILE* fp = fopen(path, "rb+"); if (!fp && errno != ENOENT) { error = fileError("Can't open ptex file for update: ", path).c_str(); } PtexWriterBase* w = 0; // use incremental writer iff incremental mode requested and file exists if (incremental && fp) { w = new PtexIncrWriter(path, fp, mt, dt, nchannels, alphachan, nfaces); } // otherwise use main writer else { PtexTexture* tex = 0; if (fp) { // got an existing file, close and reopen with PtexReader fclose(fp); // open reader for existing file tex = PtexTexture::open(path, error); if (!tex) return 0; // make sure header matches bool headerMatch = (mt == tex->meshType() && dt == tex->dataType() && nchannels == tex->numChannels() && alphachan == tex->alphaChannel() && nfaces == tex->numFaces()); if (!headerMatch) { std::stringstream str; str << "PtexWriter::edit error: header doesn't match existing file, " << "conversions not currently supported"; error = str.str().c_str(); return 0; } } w = new PtexMainWriter(path, tex, mt, dt, nchannels, alphachan, nfaces, genmipmaps); } if (!w->ok(error)) { w->release(); return 0; } return w; }
void IBLWidget::loadIBL( const char* filename ) { printf( "opening %s... ", filename ); // try and load it Ptex::String error; PtexTexture* tx = PtexTexture::open(filename, error); if (!tx) { printf( "failed\n"); return; } CKGL(); Ptex::DataType dataType = tx->dataType(); int numChannels = tx->numChannels(); int numFaces=tx->numFaces(); int faceWidth=0, faceHeight=0; if( dataType != Ptex::dt_float || numChannels != 3 || numFaces != 6 ) { printf( "not the right kind\n" ); return; } for( int i = 0; i < numFaces; i++ ) { int face = i; Ptex::Res res = tx->getFaceInfo(i).res; if( i == 0 ) { faceWidth = res.u(); faceHeight = res.v(); // printf( "size: %dx%d (%dx%d)\n", faceWidth, faceHeight, faceWidth*6, faceHeight ); envTex.create( faceWidth*6, faceHeight ); } if( faceWidth != res.u() || faceHeight != res.v() ) { printf( "error loading ptex file\n" ); return; } float* faceData = (float*)malloc( faceWidth*faceHeight*numChannels*sizeof(float) ); tx->getData( i, faceData, 0 ); // copy the data into the envmap texture for( int j = 0; j < faceHeight * faceWidth; j++ ) { color3 c( faceData[j*3+0], faceData[j*3+1], faceData[j*3+2] ); envTex.setPixel( faceWidth*face + j % faceWidth, j / faceWidth, c ); } free( faceData ); } tx->release(); printf( "success\n"); // allocate texture names (if we haven't before) if( envTexID == 0 ) { glf->glGenTextures( 1, &envTexID ); glf->glGenTextures( 1, &probTexID ); glf->glGenTextures( 1, &marginalProbTexID ); } CKGL(); // now that the envmap tex is loaded, compute the sampling data computeEnvMapSamplingData(); createGLSamplingTextures(); CKGL(); glf->glGenTextures(1, &envTexID); glf->glBindTexture( GL_TEXTURE_CUBE_MAP, envTexID ); glf->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); BitmapContainer<color3> flip; flip.create(envTex.w, envTex.h);//get face flipped to match GL thinking! for (int y=0; y < envTex.h; y++){ color3* in = &envTex.data[y*envTex.w]; color3* out = &flip.data[(envTex.h-y-1)*envTex.w]; for (int x=0; x < envTex.w; x++) out[x] = in[x]; } BitmapContainer<color3> tmp; tmp.create(envTex.h, envTex.h); CKGL(); for (int y=0; y < tmp.h; y++) for (int x=0; x < tmp.w; x++) tmp.setPixel(x, y,flip.getPixel(x+tmp.w*0, y)); glf->glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X , 0,GL_R11F_G11F_B10F, tmp.w, tmp.h, 0, GL_RGB, GL_FLOAT, tmp.getPtr() ); for (int y=0; y < tmp.h; y++) for (int x=0; x < tmp.w; x++) tmp.setPixel(x, y,flip.getPixel(x+tmp.w*1, y)); glf->glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X , 0,GL_R11F_G11F_B10F, tmp.w, tmp.h, 0, GL_RGB, GL_FLOAT, tmp.getPtr() ); for (int y=0; y < tmp.h; y++) for (int x=0; x < tmp.w; x++) tmp.setPixel(x, y,flip.getPixel(x+tmp.w*2, y)); glf->glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y , 0,GL_R11F_G11F_B10F, tmp.w, tmp.h, 0, GL_RGB, GL_FLOAT, tmp.getPtr() ); for (int y=0; y < tmp.h; y++) for (int x=0; x < tmp.w; x++) tmp.setPixel(x, y,flip.getPixel(x+tmp.w*3, y)); glf->glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y , 0,GL_R11F_G11F_B10F, tmp.w, tmp.h, 0, GL_RGB, GL_FLOAT, tmp.getPtr() ); for (int y=0; y < tmp.h; y++) for (int x=0; x < tmp.w; x++) tmp.setPixel(x, y,flip.getPixel(x+tmp.w*4, y)); glf->glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z , 0,GL_R11F_G11F_B10F, tmp.w, tmp.h, 0, GL_RGB, GL_FLOAT, tmp.getPtr() ); CKGL(); for (int y=0; y < tmp.h; y++) for (int x=0; x < tmp.w; x++) tmp.setPixel(x, y,flip.getPixel(x+tmp.w*5, y)); glf->glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z , 0,GL_R11F_G11F_B10F, tmp.w, tmp.h, 0, GL_RGB, GL_FLOAT, tmp.getPtr() ); CKGL(); glf->glGenerateMipmap(GL_TEXTURE_CUBE_MAP); glf->glBindTexture( GL_TEXTURE_CUBE_MAP, 0 ); CKGL(); }
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 }
//------------------------------------------------------------------------------ void createOsdMesh(int level, int kernel) { Ptex::String ptexError; PtexTexture *ptexColor = PtexTexture::open(g_ptexColorFile, ptexError, true); // generate Hbr representation from ptex OpenSubdiv::OsdHbrMesh * hmesh = createPTexGeo<OpenSubdiv::OsdVertex>(ptexColor); if(hmesh == NULL) return; g_normals.resize(g_positions.size(),0.0f); calcNormals( hmesh, g_positions, g_normals ); // generate Osd mesh from Hbr mesh if (g_osdmesh) delete g_osdmesh; g_osdmesh = new OpenSubdiv::OsdMesh(); g_osdmesh->Create(hmesh, level, kernel); if (g_vertexBuffer) { delete g_vertexBuffer; g_vertexBuffer = NULL; } // Hbr mesh can be deleted delete hmesh; // generate oOsdPTexture if (g_osdPTexDisplacement) delete g_osdPTexDisplacement; if (g_osdPTexOcclusion) delete g_osdPTexOcclusion; g_osdPTexDisplacement = NULL; g_osdPTexOcclusion = NULL; OpenSubdiv::OsdPTexture::SetGutterWidth(g_gutterWidth); OpenSubdiv::OsdPTexture::SetPageMargin(g_gutterWidth*8); OpenSubdiv::OsdPTexture::SetGutterDebug(g_gutterDebug); if (g_osdPTexImage) delete g_osdPTexImage; g_osdPTexImage = OpenSubdiv::OsdPTexture::Create(ptexColor, 0 /*targetmemory*/); ptexColor->release(); if (g_ptexDisplacementFile) { PtexTexture *ptexDisplacement = PtexTexture::open(g_ptexDisplacementFile, ptexError, true); g_osdPTexDisplacement = OpenSubdiv::OsdPTexture::Create(ptexDisplacement, 0); ptexDisplacement->release(); } if (g_ptexOcclusionFile) { PtexTexture *ptexOcclusion = PtexTexture::open(g_ptexOcclusionFile, ptexError, true); g_osdPTexOcclusion = OpenSubdiv::OsdPTexture::Create(ptexOcclusion, 0); ptexOcclusion->release(); } // create element array buffer if (g_elementArrayBuffer) delete g_elementArrayBuffer; g_elementArrayBuffer = g_osdmesh->CreateElementArrayBuffer(level); // create ptex coordinates buffer if (g_ptexCoordinatesTextureBuffer) delete g_ptexCoordinatesTextureBuffer; g_ptexCoordinatesTextureBuffer = g_osdmesh->CreatePtexCoordinatesTextureBuffer(level); updateGeom(); linkProgram(); linkDebugProgram(); }
//------------------------------------------------------------------------------ void createOsdMesh(int level, int kernel) { Ptex::String ptexError; PtexTexture *ptexColor = PtexTexture::open(g_ptexColorFile, ptexError, true); // generate Hbr representation from ptex OpenSubdiv::OsdHbrMesh * hmesh = createPTexGeo<OpenSubdiv::OsdVertex>(ptexColor); if(hmesh == NULL) return; g_normals.resize(g_positions.size(),0.0f); calcNormals( hmesh, g_positions, g_normals ); // generate Osd mesh from Hbr mesh if (g_osdmesh) delete g_osdmesh; g_osdmesh = new OpenSubdiv::OsdMesh(); g_osdmesh->Create(hmesh, level, kernel); if (g_vertexBuffer) { delete g_vertexBuffer; g_vertexBuffer = NULL; } // Hbr mesh can be deleted delete hmesh; // update element array buffer const std::vector<int> &indices = g_osdmesh->GetFarMesh()->GetFaceVertices(level); // generate oOsdPTexture if (g_osdPTexDisplacement) delete g_osdPTexDisplacement; if (g_osdPTexOcclusion) delete g_osdPTexOcclusion; g_osdPTexDisplacement = NULL; g_osdPTexOcclusion = NULL; OpenSubdiv::OsdPTexture::SetGutterWidth(g_gutterWidth); OpenSubdiv::OsdPTexture::SetPageMargin(g_gutterWidth*8); OpenSubdiv::OsdPTexture::SetGutterDebug(g_gutterDebug); if (g_osdPTexImage) delete g_osdPTexImage; g_osdPTexImage = OpenSubdiv::OsdPTexture::Create(ptexColor, 0 /*targetmemory*/); ptexColor->release(); if (g_ptexDisplacementFile) { PtexTexture *ptexDisplacement = PtexTexture::open(g_ptexDisplacementFile, ptexError, true); g_osdPTexDisplacement = OpenSubdiv::OsdPTexture::Create(ptexDisplacement, 0); ptexDisplacement->release(); } if (g_ptexOcclusionFile) { PtexTexture *ptexOcclusion = PtexTexture::open(g_ptexOcclusionFile, ptexError, true); g_osdPTexOcclusion = OpenSubdiv::OsdPTexture::Create(ptexOcclusion, 0); ptexOcclusion->release(); } // bind index buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer); g_numIndices = (int)indices.size(); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*g_numIndices, &(indices[0]), GL_STATIC_DRAW); updateGeom(); linkProgram(); linkDebugProgram(); }