std::vector<std::shared_ptr<Shape>> CreateCurveShape(const Transform *o2w, const Transform *w2o, bool reverseOrientation, const ParamSet ¶ms) { Float width = params.FindOneFloat("width", 1.f); Float width0 = params.FindOneFloat("width0", width); Float width1 = params.FindOneFloat("width1", width); int ncp; const Point3f *cp = params.FindPoint3f("P", &ncp); if (ncp != 4) { Error( "Must provide 4 control points for \"curve\" primitive. " "(Provided %d).", ncp); return std::vector<std::shared_ptr<Shape>>(); } CurveType type; std::string curveType = params.FindOneString("type", "flat"); if (curveType == "flat") type = CurveType::Flat; else if (curveType == "ribbon") type = CurveType::Ribbon; else if (curveType == "cylinder") type = CurveType::Cylinder; else { Error("Unknown curve type \"%s\". Using \"flat\".", curveType.c_str()); type = CurveType::Cylinder; } int nnorm; const Normal3f *n = params.FindNormal3f("N", &nnorm); if (n != nullptr) { if (type != CurveType::Ribbon) { Warning("Curve normals are only used with \"ribbon\" type curves."); n = nullptr; } else if (nnorm != 2) { Error( "Must provide two normals with \"N\" parameter for ribbon " "curves. " "(Provided %d).", nnorm); return std::vector<std::shared_ptr<Shape>>(); } } int sd = params.FindOneFloat("splitdepth", 2); if (type == CurveType::Ribbon && n == nullptr) { Error( "Must provide normals \"N\" at curve endpoints with ribbon " "curves."); return std::vector<std::shared_ptr<Shape>>(); } else return CreateCurve(o2w, w2o, reverseOrientation, cp, width0, width1, type, n, sd); }
std::vector<std::shared_ptr<Shape>> CreateTriangleMeshShape( const Transform *o2w, const Transform *w2o, bool reverseOrientation, const ParamSet ¶ms, std::map<std::string, std::shared_ptr<Texture<Float>>> *floatTextures) { int nvi, npi, nuvi, nsi, nni; const int *vi = params.FindInt("indices", &nvi); const Point3f *P = params.FindPoint3f("P", &npi); const Point2f *uvs = params.FindPoint2f("uv", &nuvi); if (!uvs) uvs = params.FindPoint2f("st", &nuvi); std::vector<Point2f> tempUVs; if (!uvs) { const Float *fuv = params.FindFloat("uv", &nuvi); if (!fuv) fuv = params.FindFloat("st", &nuvi); if (fuv) { nuvi /= 2; tempUVs.reserve(nuvi); for (int i = 0; i < nuvi; ++i) tempUVs.push_back(Point2f(fuv[2 * i], fuv[2 * i + 1])); uvs = &tempUVs[0]; } } bool discardDegenerateUVs = params.FindOneBool("discarddegenerateUVs", false); if (uvs) { if (nuvi < npi) { Error( "Not enough of \"uv\"s for triangle mesh. Expencted %d, " "found %d. Discarding.", npi, nuvi); uvs = nullptr; } else if (nuvi > npi) Warning( "More \"uv\"s provided than will be used for triangle " "mesh. (%d expcted, %d found)", npi, nuvi); } if (!vi) { Error( "Vertex indices \"indices\" not provided with triangle mesh shape"); return std::vector<std::shared_ptr<Shape>>(); } if (!P) { Error("Vertex positions \"P\" not provided with triangle mesh shape"); return std::vector<std::shared_ptr<Shape>>(); } const Vector3f *S = params.FindVector3f("S", &nsi); if (S && nsi != npi) { Error("Number of \"S\"s for triangle mesh must match \"P\"s"); S = nullptr; } const Normal3f *N = params.FindNormal3f("N", &nni); if (N && nni != npi) { Error("Number of \"N\"s for triangle mesh must match \"P\"s"); N = nullptr; } if (discardDegenerateUVs && uvs && N) { // if there are normals, check for bad uv's that // give degenerate mappings; discard them if so const int *vp = vi; for (int i = 0; i < nvi; 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 ((uvs[vp[0]].x == uvs[vp[1]].x && uvs[vp[0]].y == uvs[vp[1]].y) || (uvs[vp[1]].x == uvs[vp[2]].x && uvs[vp[1]].y == uvs[vp[2]].y) || (uvs[vp[2]].x == uvs[vp[0]].x && uvs[vp[2]].y == uvs[vp[0]].y)) { Warning( "Degenerate uv coordinates in triangle mesh. Discarding " "all uvs."); uvs = nullptr; break; } } } for (int i = 0; i < nvi; ++i) if (vi[i] >= npi) { Error( "trianglemesh has out of-bounds vertex index %d (%d \"P\" " "values were given", vi[i], npi); return std::vector<std::shared_ptr<Shape>>(); } 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, nvi / 3, vi, npi, P, S, N, uvs, alphaTex, shadowAlphaTex); }