std::shared_ptr<GonioPhotometricLight> CreateGoniometricLight( const Transform &light2world, const Medium *medium, const ParamSet ¶mSet) { Spectrum I = paramSet.FindOneSpectrum("I", Spectrum(1.0)); Spectrum sc = paramSet.FindOneSpectrum("scale", Spectrum(1.0)); std::string texname = paramSet.FindOneFilename("mapname", ""); return std::make_shared<GonioPhotometricLight>(light2world, medium, I * sc, texname); }
std::shared_ptr<ProjectionLight> CreateProjectionLight( const Transform &light2world, const Medium *medium, const ParamSet ¶mSet) { Spectrum I = paramSet.FindOneSpectrum("I", Spectrum(1.0)); Spectrum sc = paramSet.FindOneSpectrum("scale", Spectrum(1.0)); Float fov = paramSet.FindOneFloat("fov", 45.); std::string texname = paramSet.FindOneFilename("mapname", ""); return std::make_shared<ProjectionLight>(light2world, medium, I * sc, texname, fov); }
std::shared_ptr<InfiniteAreaLight> CreateInfiniteLight( const Transform &light2world, const ParamSet ¶mSet) { Spectrum L = paramSet.FindOneSpectrum("L", Spectrum(1.0)); Spectrum sc = paramSet.FindOneSpectrum("scale", Spectrum(1.0)); std::string texmap = paramSet.FindOneFilename("mapname", ""); int nSamples = paramSet.FindOneInt("nsamples", 1); if (PbrtOptions.quickRender) nSamples = std::max(1, nSamples / 4); return std::make_shared<InfiniteAreaLight>(light2world, L * sc, nSamples, texmap); }
std::vector<std::shared_ptr<Shape>> CreatePLYMesh( const Transform *o2w, const Transform *w2o, bool reverseOrientation, const ParamSet ¶ms, std::map<std::string, std::shared_ptr<Texture<Float>>> *floatTextures) { const std::string filename = params.FindOneFilename("filename", ""); p_ply ply = ply_open(filename.c_str(), rply_message_callback, 0, nullptr); if (!ply) { Error("Couldn't open PLY file \"%s\"", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } if (!ply_read_header(ply)) { Error("Unable to read the header of PLY file \"%s\"", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } p_ply_element element = nullptr; long vertexCount = 0, faceCount = 0; /* Inspect the structure of the PLY file */ while ((element = ply_get_next_element(ply, element)) != nullptr) { const char *name; long nInstances; ply_get_element_info(element, &name, &nInstances); if (!strcmp(name, "vertex")) vertexCount = nInstances; else if (!strcmp(name, "face")) faceCount = nInstances; } if (vertexCount == 0 || faceCount == 0) { Error("PLY file \"%s\" is invalid! No face/vertex elements found!", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } CallbackContext context; if (ply_set_read_cb(ply, "vertex", "x", rply_vertex_callback, &context, 0x030) && ply_set_read_cb(ply, "vertex", "y", rply_vertex_callback, &context, 0x031) && ply_set_read_cb(ply, "vertex", "z", rply_vertex_callback, &context, 0x032)) { context.p = new Point3f[vertexCount]; } else { Error("PLY file \"%s\": Vertex coordinate property not found!", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } if (ply_set_read_cb(ply, "vertex", "nx", rply_vertex_callback, &context, 0x130) && ply_set_read_cb(ply, "vertex", "ny", rply_vertex_callback, &context, 0x131) && ply_set_read_cb(ply, "vertex", "nz", rply_vertex_callback, &context, 0x132)) context.n = new Normal3f[vertexCount]; /* There seem to be lots of different conventions regarding UV coordinate * names */ if ((ply_set_read_cb(ply, "vertex", "u", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "v", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "s", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "t", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "texture_u", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "texture_v", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "texture_s", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "texture_t", rply_vertex_callback, &context, 0x221))) context.uv = new Point2f[vertexCount]; /* Allocate enough space in case all faces are quads */ context.indices = new int[faceCount * 6]; context.vertexCount = vertexCount; ply_set_read_cb(ply, "face", "vertex_indices", rply_face_callback, &context, 0); if (!ply_read(ply)) { Error("Unable to read the contents of PLY file \"%s\"", filename.c_str()); ply_close(ply); return std::vector<std::shared_ptr<Shape>>(); } ply_close(ply); if (context.error) return std::vector<std::shared_ptr<Shape>>(); // Look up an alpha texture, if applicable std::shared_ptr<Texture<Float>> alphaTex; std::string alphaTexName = params.FindTexture("alpha"); if (alphaTexName != "") { if (floatTextures->find(alphaTexName) != floatTextures->end()) alphaTex = (*floatTextures)[alphaTexName]; else Error("Couldn't find float texture \"%s\" for \"alpha\" parameter", alphaTexName.c_str()); } else if (params.FindOneFloat("alpha", 1.f) == 0.f) { alphaTex.reset(new ConstantTexture<Float>(0.f)); } std::shared_ptr<Texture<Float>> shadowAlphaTex; std::string shadowAlphaTexName = params.FindTexture("shadowalpha"); if (shadowAlphaTexName != "") { if (floatTextures->find(shadowAlphaTexName) != floatTextures->end()) shadowAlphaTex = (*floatTextures)[shadowAlphaTexName]; else Error("Couldn't find float texture \"%s\" for \"shadowalpha\" parameter", shadowAlphaTexName.c_str()); } else if (params.FindOneFloat("shadowalpha", 1.f) == 0.f) shadowAlphaTex.reset(new ConstantTexture<Float>(0.f)); bool discardDegenerateUVs = params.FindOneBool("discarddegenerateUVs", false); if (discardDegenerateUVs && context.uv && context.n) { // if there are normals, check for bad uv's that // give degenerate mappings; discard them if so const int *vp = context.indices; const Point3f *P = context.p; const Point2f *uv = context.uv; for (int i = 0; i < context.indexCtr; i += 3, vp += 3) { Float area = .5f * Cross(P[vp[0]] - P[vp[1]], P[vp[2]] - P[vp[1]]).Length(); if (area < 1e-7) continue; // ignore degenerate tris. if ((uv[vp[0]].x == uv[vp[1]].x && uv[vp[0]].y == uv[vp[1]].y) || (uv[vp[1]].x == uv[vp[2]].x && uv[vp[1]].y == uv[vp[2]].y) || (uv[vp[2]].x == uv[vp[0]].x && uv[vp[2]].y == uv[vp[0]].y)) { Warning( "Degenerate uv coordinates in triangle mesh. Discarding " "all uv."); delete[] context.uv; context.uv = nullptr; break; } } } return CreateTriangleMesh( o2w, w2o, reverseOrientation, context.indexCtr / 3, context.indices, vertexCount, context.p, nullptr, context.n, context.uv, alphaTex, shadowAlphaTex); }
std::vector<std::shared_ptr<Shape>> CreatePLYMesh( const Transform *o2w, const Transform *w2o, bool reverseOrientation, const ParamSet ¶ms, std::map<std::string, std::shared_ptr<Texture<Float>>> *floatTextures) { const std::string filename = params.FindOneFilename("filename", ""); p_ply ply = ply_open(filename.c_str(), rply_message_callback, 0, nullptr); if (!ply) { Error("Couldn't open PLY file \"%s\"", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } if (!ply_read_header(ply)) { Error("Unable to read the header of PLY file \"%s\"", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } p_ply_element element = nullptr; long vertexCount = 0, faceCount = 0; /* Inspect the structure of the PLY file */ while ((element = ply_get_next_element(ply, element)) != nullptr) { const char *name; long nInstances; ply_get_element_info(element, &name, &nInstances); if (!strcmp(name, "vertex")) vertexCount = nInstances; else if (!strcmp(name, "face")) faceCount = nInstances; } if (vertexCount == 0 || faceCount == 0) { Error("PLY file \"%s\" is invalid! No face/vertex elements found!", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } CallbackContext context; if (ply_set_read_cb(ply, "vertex", "x", rply_vertex_callback, &context, 0x030) && ply_set_read_cb(ply, "vertex", "y", rply_vertex_callback, &context, 0x031) && ply_set_read_cb(ply, "vertex", "z", rply_vertex_callback, &context, 0x032)) { context.p = new Point3f[vertexCount]; } else { Error("PLY file \"%s\": Vertex coordinate property not found!", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } if (ply_set_read_cb(ply, "vertex", "nx", rply_vertex_callback, &context, 0x130) && ply_set_read_cb(ply, "vertex", "ny", rply_vertex_callback, &context, 0x131) && ply_set_read_cb(ply, "vertex", "nz", rply_vertex_callback, &context, 0x132)) context.n = new Normal3f[vertexCount]; /* There seem to be lots of different conventions regarding UV coordinate * names */ if ((ply_set_read_cb(ply, "vertex", "u", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "v", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "s", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "t", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "texture_u", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "texture_v", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "texture_s", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "texture_t", rply_vertex_callback, &context, 0x221))) context.uv = new Point2f[vertexCount]; /* Allocate enough space in case all faces are quads */ context.indices = new int[faceCount * 6]; context.vertexCount = vertexCount; ply_set_read_cb(ply, "face", "vertex_indices", rply_face_callback, &context, 0); if (!ply_read(ply)) { Error("Unable to read the contents of PLY file \"%s\"", filename.c_str()); ply_close(ply); return std::vector<std::shared_ptr<Shape>>(); } ply_close(ply); if (context.error) return std::vector<std::shared_ptr<Shape>>(); // Look up an alpha texture, if applicable std::shared_ptr<Texture<Float>> alphaTex; std::string alphaTexName = params.FindTexture("alpha"); if (alphaTexName != "") { if (floatTextures->find(alphaTexName) != floatTextures->end()) alphaTex = (*floatTextures)[alphaTexName]; else Error("Couldn't find float texture \"%s\" for \"alpha\" parameter", alphaTexName.c_str()); } else if (params.FindOneFloat("alpha", 1.f) == 0.f) { alphaTex.reset(new ConstantTexture<Float>(0.f)); } std::shared_ptr<Texture<Float>> shadowAlphaTex; std::string shadowAlphaTexName = params.FindTexture("shadowalpha"); if (shadowAlphaTexName != "") { if (floatTextures->find(shadowAlphaTexName) != floatTextures->end()) shadowAlphaTex = (*floatTextures)[shadowAlphaTexName]; else Error( "Couldn't find float texture \"%s\" for \"shadowalpha\" " "parameter", shadowAlphaTexName.c_str()); } else if (params.FindOneFloat("shadowalpha", 1.f) == 0.f) shadowAlphaTex.reset(new ConstantTexture<Float>(0.f)); return CreateTriangleMesh(o2w, w2o, reverseOrientation, context.indexCtr / 3, context.indices, vertexCount, context.p, nullptr, context.n, context.uv, alphaTex, shadowAlphaTex); }