Esempio n. 1
0
std::vector<std::shared_ptr<Shape>> CreateCurveShape(const Transform *o2w,
                                                     const Transform *w2o,
                                                     bool reverseOrientation,
                                                     const ParamSet &params) {
    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);
}
Esempio n. 2
0
std::shared_ptr<Cylinder> CreateCylinderShape(const Transform *o2w,
                                              const Transform *w2o,
                                              bool reverseOrientation,
                                              const ParamSet &params) {
    Float radius = params.FindOneFloat("radius", 1);
    Float zmin = params.FindOneFloat("zmin", -1);
    Float zmax = params.FindOneFloat("zmax", 1);
    Float phimax = params.FindOneFloat("phimax", 360);
    return std::make_shared<Cylinder>(o2w, w2o, reverseOrientation, radius,
                                      zmin, zmax, phimax);
}
Esempio n. 3
0
std::shared_ptr<Shape> CreateSphereShape(const Transform *o2w,
                                         const Transform *w2o,
                                         bool reverseOrientation,
                                         const ParamSet &params) {
    Float radius = params.FindOneFloat("radius", 1.f);
    Float zmin = params.FindOneFloat("zmin", -radius);
    Float zmax = params.FindOneFloat("zmax", radius);
    Float phimax = params.FindOneFloat("phimax", 360.f);
    return std::make_shared<Sphere>(o2w, w2o, reverseOrientation, radius, zmin,
                                    zmax, phimax);
}
Esempio n. 4
0
std::shared_ptr<Disk> CreateDiskShape(const Transform *o2w,
                                      const Transform *w2o,
                                      bool reverseOrientation,
                                      const ParamSet &params) {
    Float height = params.FindOneFloat("height", 0.);
    Float radius = params.FindOneFloat("radius", 1);
    Float inner_radius = params.FindOneFloat("innerradius", 0);
    Float phimax = params.FindOneFloat("phimax", 360);
    return std::make_shared<Disk>(o2w, w2o, reverseOrientation, height, radius,
                                  inner_radius, phimax);
}
Esempio n. 5
0
std::shared_ptr<Medium> MakeMedium(const std::string &name,
                                   const ParamSet &paramSet,
                                   const Transform &medium2world) {
    Float sig_a_rgb[3] = {.0011f, .0024f, .014f},
          sig_s_rgb[3] = {2.55f, 3.21f, 3.77f};
    Spectrum sig_a = Spectrum::FromRGB(sig_a_rgb),
             sig_s = Spectrum::FromRGB(sig_s_rgb);
    std::string preset = paramSet.FindOneString("preset", "");
    bool found = GetMediumScatteringProperties(preset, &sig_a, &sig_s);
    if (preset != "" && !found)
        Warning("Material preset \"%s\" not found.  Using defaults.",
                preset.c_str());
    Float scale = paramSet.FindOneFloat("scale", 1.f);
    Float g = paramSet.FindOneFloat("g", 0.0f);
    sig_a = paramSet.FindOneSpectrum("sigma_a", sig_a) * scale;
    sig_s = paramSet.FindOneSpectrum("sigma_s", sig_s) * scale;
    Medium *m = NULL;
    if (name == "homogeneous") {
        m = new HomogeneousMedium(sig_a, sig_s, g);
    } else if (name == "heterogeneous") {
        int nitems;
        const Float *data = paramSet.FindFloat("density", &nitems);
        if (!data) {
            Error("No \"density\" values provided for heterogeneous medium?");
            return NULL;
        }
        int nx = paramSet.FindOneInt("nx", 1);
        int ny = paramSet.FindOneInt("ny", 1);
        int nz = paramSet.FindOneInt("nz", 1);
        Point3f p0 = paramSet.FindOnePoint3f("p0", Point3f(0.f, 0.f, 0.f));
        Point3f p1 = paramSet.FindOnePoint3f("p1", Point3f(1.f, 1.f, 1.f));
        if (nitems != nx * ny * nz) {
            Error(
                "GridDensityMedium has %d density values; expected nx*ny*nz = "
                "%d",
                nitems, nx * ny * nz);
            return NULL;
        }
        Transform data2Medium = Translate(Vector3f(p0)) *
                                Scale(p1.x - p0.x, p1.y - p0.y, p1.z - p0.z);
        m = new GridDensityMedium(sig_a, sig_s, g, nx, ny, nz,
                                  medium2world * data2Medium, data);
    } else
        Warning("Medium \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return std::shared_ptr<Medium>(m);
}
Esempio n. 6
0
NaiadFoam::NaiadFoam(const Transform *o2w, const Transform *w2o,
                     bool ro, const ParamSet &params): Shape(o2w, w2o, ro) {

    Nb::begin();

    int nFoamEmps;
    const string * empStr = params.FindString("emp", &nFoamEmps);
    const string * bodyStr = params.FindString("body", &nFoamEmps);

    for (int i = 0; i < nFoamEmps; ++i) {
        Nb::EmpReader empReader(empStr[i].c_str(),"*");
        const Nb::Body * body = empReader.ejectBody(bodyStr[i].c_str());
        const Nb::ParticleShape & particle = body->constParticleShape();

        bb = BBox(Point(particle.min().v[0],
                        particle.min().v[1],
                        particle.min().v[2]),
                  Point(particle.max().v[0],
                        particle.max().v[1],
                        particle.max().v[2]));

        //Total amount of particles
        const int64_t nParticles = particle.size();
        printf("Found %i particles in %s\n", nParticles, empStr[i].c_str());

        //Number of blocks
        const int nBlocks = particle.constBlocks3f(0).block_count();

        for (int64_t blockIdx = 0; blockIdx < nBlocks; ++blockIdx) {
            boxes.push_back(new NaiadFoamBox(o2w,w2o,ro,this,particle,blockIdx));
        }
    }

    foamPlane = new std::vector<float>(441000,0);

    FoamInLowerBound  = params.FindOneFloat("FoamInLowerBound",0.f);
    FoamInUpperBound  = params.FindOneFloat("FoamInUpperLowerBound",255.f);
    FoamInGamma       = params.FindOneFloat("FoamInGamma",1.f);
    FoamOutLowerBound = params.FindOneFloat("FoamOutUpperLowerBound",0.f);
    FoamOutUpperBound = params.FindOneFloat("FoamOutUpperLowerBound",255.f);

    printf("%f %f %f %f %f\n", FoamInLowerBound, FoamInUpperBound, FoamInGamma, FoamOutLowerBound, FoamOutUpperBound);

    cur = this;
}
Esempio n. 7
0
std::shared_ptr<ProjectionLight> CreateProjectionLight(
    const Transform &light2world, const Medium *medium,
    const ParamSet &paramSet) {
    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);
}
Esempio n. 8
0
std::shared_ptr<Shape> CreateHyperboloidShape(const Transform *o2w,
                                              const Transform *w2o,
                                              bool reverseOrientation,
                                              const ParamSet &params) {
    Point3f p1 = params.FindOnePoint3f("p1", Point3f(0, 0, 0));
    Point3f p2 = params.FindOnePoint3f("p2", Point3f(1, 1, 1));
    Float phimax = params.FindOneFloat("phimax", 360);
    return std::make_shared<Hyperboloid>(o2w, w2o, reverseOrientation, p1, p2,
                                         phimax);
}
Esempio n. 9
0
std::shared_ptr<SpotLight> CreateSpotLight(const Transform &l2w,
                                           const Medium *medium,
                                           const ParamSet &paramSet) {
    Spectrum I = paramSet.FindOneSpectrum("I", Spectrum(1.0));
    Spectrum sc = paramSet.FindOneSpectrum("scale", Spectrum(1.0));
    Float coneangle = paramSet.FindOneFloat("coneangle", 30.);
    Float conedelta = paramSet.FindOneFloat("conedeltaangle", 5.);
    // Compute spotlight world to light transformation
    Point3f from = paramSet.FindOnePoint3f("from", Point3f(0, 0, 0));
    Point3f to = paramSet.FindOnePoint3f("to", Point3f(0, 0, 1));
    Vector3f dir = Normalize(to - from);
    Vector3f du, dv;
    CoordinateSystem(dir, &du, &dv);
    Transform dirToZ =
        Transform(Matrix4x4(du.x, du.y, du.z, 0., dv.x, dv.y, dv.z, 0., dir.x,
                            dir.y, dir.z, 0., 0, 0, 0, 1.));
    Transform light2world =
        l2w * Translate(Vector3f(from.x, from.y, from.z)) * Inverse(dirToZ);
    return std::make_shared<SpotLight>(light2world, medium, I * sc, coneangle,
                                       coneangle - conedelta);
}
Esempio n. 10
0
std::vector<std::shared_ptr<Shape>> CreatePLYMesh(
    const Transform *o2w, const Transform *w2o, bool reverseOrientation,
    const ParamSet &params,
    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);
}
Esempio n. 11
0
Filter CreateBoxFilter(const ParamSet &ps) {
    float xw = ps.FindOneFloat("xwidth", 0.5f);
    float yw = ps.FindOneFloat("ywidth", 0.5f);
    return Filter(xw,yw,boxFilter(xw,yw));
}
Esempio n. 12
0
std::vector<std::shared_ptr<Shape>> CreateNURBS(const Transform *o2w,
                                                const Transform *w2o,
                                                bool reverseOrientation,
                                                const ParamSet &params) {
    int nu = params.FindOneInt("nu", -1);
    if (nu == -1) {
        Error("Must provide number of control points \"nu\" with NURBS shape.");
        return std::vector<std::shared_ptr<Shape>>();
    }

    int uorder = params.FindOneInt("uorder", -1);
    if (uorder == -1) {
        Error("Must provide u order \"uorder\" with NURBS shape.");
        return std::vector<std::shared_ptr<Shape>>();
    }
    int nuknots, nvknots;
    const Float *uknots = params.FindFloat("uknots", &nuknots);
    if (uknots == nullptr) {
        Error("Must provide u knot vector \"uknots\" with NURBS shape.");
        return std::vector<std::shared_ptr<Shape>>();
    }

    if (nuknots != nu + uorder) {
        Error(
            "Number of knots in u knot vector %d doesn't match sum of "
            "number of u control points %d and u order %d.",
            nuknots, nu, uorder);
        return std::vector<std::shared_ptr<Shape>>();
    }

    Float u0 = params.FindOneFloat("u0", uknots[uorder - 1]);
    Float u1 = params.FindOneFloat("u1", uknots[nu]);

    int nv = params.FindOneInt("nv", -1);
    if (nv == -1) {
        Error("Must provide number of control points \"nv\" with NURBS shape.");
        return std::vector<std::shared_ptr<Shape>>();
    }

    int vorder = params.FindOneInt("vorder", -1);
    if (vorder == -1) {
        Error("Must provide v order \"vorder\" with NURBS shape.");
        return std::vector<std::shared_ptr<Shape>>();
    }

    const Float *vknots = params.FindFloat("vknots", &nvknots);
    if (vknots == nullptr) {
        Error("Must provide v knot vector \"vknots\" with NURBS shape.");
        return std::vector<std::shared_ptr<Shape>>();
    }

    if (nvknots != nv + vorder) {
        Error(
            "Number of knots in v knot vector %d doesn't match sum of "
            "number of v control points %d and v order %d.",
            nvknots, nv, vorder);
        return std::vector<std::shared_ptr<Shape>>();
    }

    Float v0 = params.FindOneFloat("v0", vknots[vorder - 1]);
    Float v1 = params.FindOneFloat("v1", vknots[nv]);

    bool isHomogeneous = false;
    int npts;
    const Float *P = (const Float *)params.FindPoint3f("P", &npts);
    if (!P) {
        P = params.FindFloat("Pw", &npts);
        if (!P) {
            Error(
                "Must provide control points via \"P\" or \"Pw\" parameter to "
                "NURBS shape.");
            return std::vector<std::shared_ptr<Shape>>();
        }
        if ((npts % 4) != 0) {
            Error(
                "Number of \"Pw\" control points provided to NURBS shape must "
                "be "
                "multiple of four");
            return std::vector<std::shared_ptr<Shape>>();
        }
        npts /= 4;
        isHomogeneous = true;
    }
    if (npts != nu * nv) {
        Error("NURBS shape was expecting %dx%d=%d control points, was given %d",
              nu, nv, nu * nv, npts);
        return std::vector<std::shared_ptr<Shape>>();
    }

    // Compute NURBS dicing rates
    int diceu = 30, dicev = 30;
    std::unique_ptr<Float[]> ueval(new Float[diceu]);
    std::unique_ptr<Float[]> veval(new Float[dicev]);
    std::unique_ptr<Point3f[]> evalPs(new Point3f[diceu * dicev]);
    std::unique_ptr<Normal3f[]> evalNs(new Normal3f[diceu * dicev]);
    int i;
    for (i = 0; i < diceu; ++i)
        ueval[i] = Lerp((float)i / (float)(diceu - 1), u0, u1);
    for (i = 0; i < dicev; ++i)
        veval[i] = Lerp((float)i / (float)(dicev - 1), v0, v1);

    // Evaluate NURBS over grid of points
    memset(evalPs.get(), 0, diceu * dicev * sizeof(Point3f));
    memset(evalNs.get(), 0, diceu * dicev * sizeof(Point3f));
    std::unique_ptr<Point2f[]> uvs(new Point2f[diceu * dicev]);

    // Turn NURBS into triangles
    std::unique_ptr<Homogeneous3[]> Pw(new Homogeneous3[nu * nv]);
    if (isHomogeneous) {
        for (int i = 0; i < nu * nv; ++i) {
            Pw[i].x = P[4 * i];
            Pw[i].y = P[4 * i + 1];
            Pw[i].z = P[4 * i + 2];
            Pw[i].w = P[4 * i + 3];
        }
    } else {
        for (int i = 0; i < nu * nv; ++i) {
            Pw[i].x = P[3 * i];
            Pw[i].y = P[3 * i + 1];
            Pw[i].z = P[3 * i + 2];
            Pw[i].w = 1.;
        }
    }

    for (int v = 0; v < dicev; ++v) {
        for (int u = 0; u < diceu; ++u) {
            uvs[(v * diceu + u)].x = ueval[u];
            uvs[(v * diceu + u)].y = veval[v];

            Vector3f dpdu, dpdv;
            Point3f pt = NURBSEvaluateSurface(uorder, uknots, nu, ueval[u],
                                              vorder, vknots, nv, veval[v],
                                              Pw.get(), &dpdu, &dpdv);
            evalPs[v * diceu + u].x = pt.x;
            evalPs[v * diceu + u].y = pt.y;
            evalPs[v * diceu + u].z = pt.z;
            evalNs[v * diceu + u] = Normal3f(Normalize(Cross(dpdu, dpdv)));
        }
    }

    // Generate points-polygons mesh
    int nTris = 2 * (diceu - 1) * (dicev - 1);
    std::unique_ptr<int[]> vertices(new int[3 * nTris]);
    int *vertp = vertices.get();
    // Compute the vertex offset numbers for the triangles
    for (int v = 0; v < dicev - 1; ++v) {
        for (int u = 0; u < diceu - 1; ++u) {
#define VN(u, v) ((v)*diceu + (u))
            *vertp++ = VN(u, v);
            *vertp++ = VN(u + 1, v);
            *vertp++ = VN(u + 1, v + 1);

            *vertp++ = VN(u, v);
            *vertp++ = VN(u + 1, v + 1);
            *vertp++ = VN(u, v + 1);
#undef VN
        }
    }
    int nVerts = diceu * dicev;

    return CreateTriangleMesh(o2w, w2o, reverseOrientation, nTris,
                              vertices.get(), nVerts, evalPs.get(), nullptr,
                              evalNs.get(), uvs.get(), nullptr);
}
Esempio n. 13
0
std::vector<std::shared_ptr<Shape>> CreatePLYMesh(
    const Transform *o2w, const Transform *w2o, bool reverseOrientation,
    const ParamSet &params,
    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);
}
Esempio n. 14
0
// NaiadMesh Method Definitions
NaiadMesh::NaiadMesh(const Transform *o2w, const Transform *w2o,
        bool ro, const ParamSet &params)
    : Shape(o2w, w2o, ro) {
    Nb::begin();

    const char * empStr = params.FindOneString("emp","error").c_str();
    const char * bodyStr = params.FindOneString("body","error").c_str();
    Nb::EmpReader empReader(empStr,"*");
    const Nb::Body * body = empReader.ejectBody(bodyStr);

    //Load shapes from Naiad body
    const Nb::TriangleShape& triangle = body->constTriangleShape();
    const Nb::PointShape& point = body->constPointShape();

    //Get buffers
    const Nb::Buffer3f& posBuf(point.constBuffer3f("position"));
    const Nb::Buffer3i& triIdxBuf(triangle.constBuffer3i("index"));

    ntris = triIdxBuf.size();
    nverts = posBuf.size();

    std::cout << "NaiadMesh:: Found " << nverts << " vertices." << std::endl;
    std::cout << "NaiadMesh:: Found " << ntris << " triangles." << std::endl;

    vertexIndex = new int[3 * ntris];
    for (int i = 0; i < ntris; ++i) {
        vertexIndex[3*i    ] = triIdxBuf[i].v[0];
        vertexIndex[3*i + 1] = triIdxBuf[i].v[1];
        vertexIndex[3*i + 2] = triIdxBuf[i].v[2];
    }
    //memcpy(vertexIndex, &triIdxBuf[0], 3 * ntris * sizeof(int));

    float dispSurface = params.FindOneFloat("disp_surface",0.f);

    p = new Point[nverts];
    for (int i = 0; i < nverts; ++i) {
        Point P(posBuf[i].v[0], posBuf[i].v[1], posBuf[i].v[2]);
        if (dispSurface) {
            const Nb::Buffer3f& normalBuf(point.constBuffer3f("normal"));
            P.x += normalBuf[i].v[0] * dispSurface;
            P.y += normalBuf[i].v[1] * dispSurface;
            P.z += normalBuf[i].v[2] * dispSurface;
        }
        p[i] = (*ObjectToWorld)(P);

#ifdef VDB
        if (ntris > 50000) {
            vdb_sample(0.1);
            vdb_color(0.5f, 0.8f, 1.0f);
        } else {
            vdb_sample(1.0);
            vdb_color(0.5f, 0.5f, 0.5f);
        }

        vdb_point(p[i].x,p[i].y,p[i].z);
#endif
    }

    string uv_empStr = params.FindOneString("uv_emp","error");
    if (uv_empStr != string("error")) {
        Nb::EmpReader empReaderUV(uv_empStr.c_str(),"*");
        string uv_bodyStr = params.FindOneString("uv_body","error");
        const Nb::Body * bodyUV = empReaderUV.ejectBody(uv_bodyStr.c_str());

        const Nb::TriangleShape& tUV = bodyUV->constTriangleShape();
        const Nb::Buffer3i& uvIdx(tUV.constBuffer3i("index"));
        const Nb::Buffer3f& bufU(tUV.constBuffer3f("u"));
        const Nb::Buffer3f& bufV(tUV.constBuffer3f("v"));
        uvs = new float[2*nverts];
        for (int i = 0; i < uvIdx.size(); ++i) {
            int v0 = triIdxBuf[i].v[0];
            int v1 = triIdxBuf[i].v[1];
            int v2 = triIdxBuf[i].v[2];
            uvs[2*v0]     = bufU[i].v[0];
            uvs[2*v0 + 1] = bufV[i].v[0];
            uvs[2*v1]     = bufU[i].v[1];
            uvs[2*v1 + 1] = bufV[i].v[1];
            uvs[2*v2]     = bufU[i].v[2];
            uvs[2*v2 + 1] = bufV[i].v[2];
        }
    } else uvs = NULL;

    //No need for these parameters yet.
    //uvs = NULL;
    n = NULL;
    s = NULL;

    //For foam zbuffer
    foam_block = params.FindOneFloat("foam_block", 0.f);

    Nb::end();
}
Esempio n. 15
0
std::vector<std::shared_ptr<Shape>> CreateTriangleMeshShape(
    const Transform *o2w, const Transform *w2o, bool reverseOrientation,
    const ParamSet &params,
    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);
}
Esempio n. 16
0
DistanceEstimatorParams::DistanceEstimatorParams(const ParamSet &params) {
  maxIters = params.FindOneInt("maxiters", 1000);
  hitEpsilon = params.FindOneFloat("hitepsilon", 1e-5f);
  rayEpsilonMultiplier = params.FindOneFloat("rayepsilonmultiplier", 100.f);
  normalEpsilon = params.FindOneFloat("normalepsilon", 1e-6f);
}