Пример #1
0
void Mesh::addChild(NoriObject *obj) {
	switch (obj->getClassType()) {
		case EBSDF:
			if (m_bsdf)
				throw NoriException("Mesh: tried to register multiple BSDF instances!");
			m_bsdf = static_cast<BSDF *>(obj);
			break;

		default:
			throw NoriException(QString("Mesh::addChild(<%1>) is not supported!").arg(
				classTypeName(obj->getClassType())));
	}
}
Пример #2
0
void PerlinTexture::addChild(NoriObject *obj) {
    switch (obj->getClassType()) {
    case ESampler:
        if (m_sampler)
            throw NoriException("There can only be one sampler per scene!");
        m_sampler = static_cast<Sampler *>(obj);
        createTexture();
        break;

    default:
        throw NoriException("Scene::addChild(<%s>) is not supported!",
                            classTypeName(obj->getClassType()));
    }
}
Пример #3
0
	HeterogeneousMedium(const PropertyList &propList) {
		// Denotes the scattering albedo
		m_albedo = propList.getColor("albedo");

		// An (optional) transformation that converts between medium and world coordinates
		m_worldToMedium = propList.getTransform("toWorld", Transform()).inverse();

		// Optional multiplicative factor that will be applied to all density values in the file
		m_densityMultiplier = propList.getFloat("densityMultiplier", 1.0f);

		m_filename = propList.getString("filename");
		QByteArray filename = m_filename.toLocal8Bit();
		QFile file(m_filename);

		if (!file.exists())
			throw NoriException(QString("The file \"%1\" does not exist!").arg(m_filename));

		/* Parse the file header */
		file.open(QIODevice::ReadOnly);
		QDataStream stream(&file);
		stream.setByteOrder(QDataStream::LittleEndian);

		qint8 header[3], version; qint32 type;
		stream >> header[0] >> header[1] >> header[2] >> version >> type;

		if (memcmp(header, "VOL", 3) != 0 || version != 3)
			throw NoriException("This is not a valid volume data file!");

		stream >> m_resolution.x() >> m_resolution.y() >> m_resolution.z();
		file.close();

		cout << "Mapping \"" << filename.data() << "\" (" << m_resolution.x()
			<< "x" << m_resolution.y() << "x" << m_resolution.z() << ") into memory .." << endl;

		m_fileSize = (size_t) file.size();
		#if defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS)
			int fd = open(filename.data(), O_RDONLY);
			if (fd == -1)
				throw NoriException(QString("Could not open \"%1\"!").arg(m_filename));
			m_data = (float *) mmap(NULL, m_fileSize, PROT_READ, MAP_SHARED, fd, 0);
			if (m_data == NULL)
				throw NoriException("mmap(): failed.");
			if (close(fd) != 0)
				throw NoriException("close(): unable to close file descriptor!");
		#elif defined(PLATFORM_WINDOWS)
			m_file = CreateFileA(filename.data(), GENERIC_READ, 
				FILE_SHARE_READ, NULL, OPEN_EXISTING, 
				FILE_ATTRIBUTE_NORMAL, NULL);
			if (m_file == INVALID_HANDLE_VALUE)
				throw NoriException(QString("Could not open \"%1\"!").arg(m_filename));
			m_fileMapping = CreateFileMapping(m_file, NULL, PAGE_READONLY, 0, 0, NULL);
			if (m_fileMapping == NULL)
				throw NoriException("CreateFileMapping(): failed.");
			m_data = (float *) MapViewOfFile(m_fileMapping, FILE_MAP_READ, 0, 0, 0);
			if (m_data == NULL)
				throw NoriException("MapViewOfFile(): failed.");
		#endif

		m_data += 12; // Shift past the header
	}
Пример #4
0
NORI_NAMESPACE_BEGIN

void NoriObject::addChild(NoriObject *) {
	throw NoriException(QString("NoriObject::addChild() is not "
		"implemented for objects of type '%1'!").arg(
			classTypeName(getClassType())));
}
Пример #5
0
NORI_NAMESPACE_BEGIN

void NoriObject::addChild(NoriObject *) {
    throw NoriException(
        "NoriObject::addChild() is not implemented for objects of type '%s'!",
        classTypeName(getClassType()));
}
Пример #6
0
	WavefrontOBJ(const PropertyList &propList) {
		typedef boost::unordered_map<OBJVertex, uint32_t, OBJVertexHash> VertexMap;

		/* Process the OBJ-file line by line */	
		QString filename = propList.getString("filename");
		QFile input(filename);
		if (!input.open(QIODevice::ReadOnly | QIODevice::Text))
			throw NoriException(QString("Cannot open \"%1\"").arg(filename));

		Transform trafo = propList.getTransform("toWorld", Transform());

		cout << "Loading \"" << qPrintable(filename) << "\" .." << endl;
		m_name = filename;

		QTextStream stream(&input);
		QTextStream line;
		QString temp, prefix;

		std::vector<Point3f>   positions;
		std::vector<Point2f>   texcoords;
		std::vector<Normal3f>  normals;
		std::vector<uint32_t>  indices;
		std::vector<OBJVertex> vertices;
		VertexMap vertexMap;

		while (!(temp = stream.readLine()).isNull()) {
			line.setString(&temp);

			line >> prefix;
			if (prefix == "v") {
				Point3f p;
				line >> p.x() >> p.y() >> p.z();
				p = trafo * p;
				positions.push_back(p);
			} else if (prefix == "vt") {
Пример #7
0
void Mesh::addChild(NoriObject *obj) {
    switch (obj->getClassType()) {
        case EBSDF:
            if (m_bsdf)
                throw NoriException(
                    "Mesh: tried to register multiple BSDF instances!");
            m_bsdf = static_cast<BSDF *>(obj);
            break;
        case ETEXTURE:
            if (m_texture)
                throw NoriException(
                    "Mesh: tried to register multiple texture instances!");
            m_texture = static_cast<Texture *>(obj);
        break;
        case EBUMPMAP:
            if (m_bumpmap)
                throw NoriException(
                    "Mesh: tried to register multiple bumpmap instances!");
            m_bumpmap = static_cast<BumpTexture *>(obj);
        break;
        case EMIXTEXTURE:
            if (m_texture)
                throw NoriException(
                    "Mesh: tried to register multiple texture instances!");
            m_texture = static_cast<Texture *>(obj);

        break;
        case EMIXBUMPMAP:
            if (m_bumpmap)
                throw NoriException(
                    "Mesh: tried to register multiple bumpmap instances!");
            m_bumpmap = static_cast<BumpTexture *>(obj);
        break;
        case EEmitter: {
                Emitter *emitter = static_cast<Emitter *>(obj);
                if (m_emitter)
                    throw NoriException(
                        "Mesh: tried to register multiple Emitter instances!");
                m_emitter = emitter;
            }
            break;
        case EMedium: {

            Medium *media = static_cast<Medium *>(obj);
            if (m_medium)
                throw NoriException(
                    "Mesh: tried to register multiple medium instances!");
            m_medium = media;

        }
        break;

        default:
            throw NoriException("Mesh::addChild(<%s>) is not supported!",
                                classTypeName(obj->getClassType()));
    }
}
Пример #8
0
	virtual ~HeterogeneousMedium() {
		if (m_data) {
			m_data -= 12;

			cout << "Unmapping \"" << qPrintable(m_filename) << "\" from memory.." << endl;
			#if defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS)
				int retval = munmap(m_data, m_fileSize);
				if (retval != 0)
					throw NoriException("munmap(): unable to unmap memory!");
			#elif defined(PLATFORM_WINDOWS)
				if (!UnmapViewOfFile(m_data))
					throw NoriException("UnmapViewOfFile(): unable to unmap memory region");
				if (!CloseHandle(m_fileMapping))
					throw NoriException("CloseHandle(): unable to close file mapping!");
				if (!CloseHandle(m_file))
					throw NoriException("CloseHandle(): unable to close file");
			#endif
		}
	}
Пример #9
0
        /**
         * \brief Directly sample the lights, providing a sample weighted by 1/pdf
         * where pdf is the probability of sampling that given sample
         * 
         * \param scene
         * the scene to work with
         * 
         * \param lRec
         * the luminaire information storage
         * 
         * \param _sample
         * the 2d uniform sample
         * 
         * \return the sampled light radiance including its geometric, visibility and pdf weights
         */
        inline Color3f sampleLights(const Scene *scene, LuminaireQueryRecord &lRec, const Point2f &_sample) const {
                Point2f sample(_sample);
                const std::vector<Luminaire *> &luminaires = scene->getLuminaires();

                if (luminaires.size() == 0)
                        throw NoriException("LightIntegrator::sampleLights(): No luminaires were defined!");

                // TODO Implement the following steps
                // and take care of using the good G, V terms to work with the Li method below

                // 1. Choose one luminaire at random

                    lRec.luminaire = luminaires[rand() % (luminaires.size())]; // Tirage pas tout a fait uniforme (mais ca suffit je pense)


                // 2. Sample the position on the luminaire mesh
                // using Mesh::samplePosition(const Point2d &sample, Point3f &p, Normal3f &n)

                    const Mesh* lum_mesh=getMesh(lRec.luminaire);
                    lum_mesh->samplePosition(sample, lRec.p, lRec.n);

                    lRec.d = lRec.p - lRec.ref; // Vecteur vers la source de lumiere
                    lRec.dist = lRec.d.norm();  // Distance
                    lRec.d /= lRec.dist;        // Direction

                // 3. Compute geometry term G and visibility term on the luminaire's side (no cos(w) of the mesh side)
                // as well as the pdf of that point being found
                // use Mesh::pdf to get the probability of choosing the point in Mesh::samplePosition

                    // Pdf
                    lRec.pdf = lum_mesh->pdf();

                    // Visibility
                    Intersection its;
                    Ray3f ray(lRec.ref, lRec.d);
                    float V = 1.0f;

                    // N'arrive jamais a priori
                    if(!scene->rayIntersect(ray, its))
                        V = 0.0f;

                    // Permet de se debarrasser de la comparaison de float.
                    // Marche si les sources de lumieres sont convexes (ce qui est le cas ^^) grace au test de direction ci-apres (dans G).
                    else if (its.mesh != lum_mesh)
                        V = 0.0f;

                    // Geometry
                    float G = std::max(0.0f, -(lRec.d).dot(lRec.n)/(lRec.dist*lRec.dist)); // max(0, ...) pour annuler un eclairage dans la mauvaise direction

                // 4. Return radiance emitted from luminaire multiplied by the appropriate terms G, V ...

                    return lRec.luminaire->getColor()*V*G/lRec.pdf; // Il manque juste le cos(theta') et la BRDF
        }
Пример #10
0
NORI_NAMESPACE_BEGIN

Bitmap::Bitmap(const std::string &filename) {
    Imf::InputFile file(filename.c_str());
    const Imf::Header &header = file.header();
    const Imf::ChannelList &channels = header.channels();

    Imath::Box2i dw = file.header().dataWindow();
    resize(dw.max.y - dw.min.y + 1, dw.max.x - dw.min.x + 1);

    cout << "Reading a " << cols() << "x" << rows() << " OpenEXR file from \""
         << filename << "\"" << endl;

    const char *ch_r = nullptr, *ch_g = nullptr, *ch_b = nullptr;
    for (Imf::ChannelList::ConstIterator it = channels.begin(); it != channels.end(); ++it) {
        std::string name = toLower(it.name());

        if (it.channel().xSampling != 1 || it.channel().ySampling != 1) {
            /* Sub-sampled layers are not supported */
            continue;
        }

        if (!ch_r && (name == "r" || name == "red" || 
                endsWith(name, ".r") || endsWith(name, ".red"))) {
            ch_r = it.name();
        } else if (!ch_g && (name == "g" || name == "green" || 
                endsWith(name, ".g") || endsWith(name, ".green"))) {
            ch_g = it.name();
        } else if (!ch_b && (name == "b" || name == "blue" || 
                endsWith(name, ".b") || endsWith(name, ".blue"))) {
            ch_b = it.name();
        }
    }

    if (!ch_r || !ch_g || !ch_b)
        throw NoriException("This is not a standard RGB OpenEXR file!");

    size_t compStride = sizeof(float),
           pixelStride = 3 * compStride,
           rowStride = pixelStride * cols();

    char *ptr = reinterpret_cast<char *>(data());

    Imf::FrameBuffer frameBuffer;
    frameBuffer.insert(ch_r, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
    frameBuffer.insert(ch_g, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
    frameBuffer.insert(ch_b, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); 
    file.setFrameBuffer(frameBuffer);
    file.readPixels(dw.min.y, dw.max.y);

    m_totalLuminance = getTotalLuminace();
}
Пример #11
0
void Mesh::addChild(NoriObject *obj) {
	switch (obj->getClassType()) {
		case EBSDF:
			if (m_bsdf)
				throw NoriException("Mesh: tried to register multiple BSDF instances!");
			m_bsdf = static_cast<BSDF *>(obj);
			break;
		case ELuminaire:
			if (m_luminaire)
				throw NoriException("Mesh: tried to register multiple luminaire instances!");
			m_luminaire = static_cast<Luminaire*>(obj);
			m_luminaire -> setMesh(this);
			break;
		case ETEXTURE:
			if (m_texture)
				throw NoriException("Mesh: tried to register multiple texture instances!");
			m_texture = static_cast<Texture*>(obj);
			break;
		default:
			throw NoriException(QString("Mesh::addChild(<%1>) is not supported!").arg(
				classTypeName(obj->getClassType())));
	}
}
Пример #12
0
    void addChild(NoriObject *obj) {
        switch (obj->getClassType()) {
            case EBSDF:
                m_bsdfs.push_back(static_cast<BSDF *>(obj));
                break;

            case EScene:
                m_scenes.push_back(static_cast<Scene *>(obj));
                break;

            default:
                throw NoriException("StudentsTTest::addChild(<%s>) is not supported!",
                    classTypeName(obj->getClassType()));
        }
    }
Пример #13
0
	Color3f evalTransmittance(const Ray3f &_ray, Sampler *sampler) const {
		/* Transform the ray into the local coordinate system */
		Ray3f ray = m_worldToMedium * _ray;

		throw NoriException("HeterogeneousMedium::evalTransmittance(): not implemented!");
	}
Пример #14
0
 /// Return the mesh corresponding to a given luminaire
 inline const Mesh *getMesh(const Luminaire *lum) const {
         const Mesh *mesh = dynamic_cast<const Mesh *> (lum->getParent());
         if (!mesh) throw NoriException("Unhandled type of luminaire!");
         return mesh;
 }
Пример #15
0
NORI_NAMESPACE_BEGIN

NoriObject *loadFromXML(const std::string &filename) {
    /* Load the XML file using 'pugi' (a tiny self-contained XML parser implemented in C++) */
    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_file(filename.c_str());

    /* Helper function: map a position offset in bytes to a more readable row/column value */
    auto offset = [&](ptrdiff_t pos) -> std::string {
        std::fstream is(filename);
        char buffer[1024];
        int line = 0, linestart = 0, offset = 0;
        while (is.good()) {
            is.read(buffer, sizeof(buffer));
            for (int i = 0; i < is.gcount(); ++i) {
                if (buffer[i] == '\n') {
                    if (offset + i >= pos)
                        return tfm::format("row %i, col %i", line + 1, pos - linestart);
                    ++line;
                    linestart = offset + i;
                }
            }
            offset += (int) is.gcount();
        }
        return "byte offset " + std::to_string(pos);
    };

    if (!result) /* There was a parser / file IO error */
        throw NoriException("Error while parsing \"%s\": %s (at %s)", filename, result.description(), offset(result.offset));

    /* Set of supported XML tags */
    enum ETag {
        /* Object classes */
        EScene                = NoriObject::EScene,
        EMesh                 = NoriObject::EMesh,
        EBSDF                 = NoriObject::EBSDF,
        ETEXTURE              = NoriObject::ETEXTURE,
        EPERLIN               = NoriObject::EPERLIN,
        EMIXTEXTURE           = NoriObject::EMIXTEXTURE,
        EMIXBUMPMAP           = NoriObject::EMIXBUMPMAP,
        EBUMPMAP              = NoriObject::EBUMPMAP,
        EPhaseFunction        = NoriObject::EPhaseFunction,
        EEmitter              = NoriObject::EEmitter,
        EMedium               = NoriObject::EMedium,
        EVolume               = NoriObject::EVolume,
        ECamera               = NoriObject::ECamera,
        EIntegrator           = NoriObject::EIntegrator,
        ESampler              = NoriObject::ESampler,
        ETest                 = NoriObject::ETest,
        EReconstructionFilter = NoriObject::EReconstructionFilter,

        /* Properties */
        EBoolean = NoriObject::EClassTypeCount,
        EInteger,
        EFloat,
        EString,
        EPoint,
        EVector,
        EColor,
        ETransform,
        ETranslate,
        EMatrix,
        ERotate,
        EScale,
        ELookAt,

        EInvalid
    };

    /* Create a mapping from tag names to tag IDs */
    std::map<std::string, ETag> tags;
    tags["scene"]      = EScene;
    tags["mesh"]       = EMesh;
    tags["bsdf"]       = EBSDF;
    tags["texture"]    = ETEXTURE;
    tags["bumpmap"]    = EBUMPMAP;
    tags["perlin"]     = EPERLIN;
    tags["mixTexture"] = EMIXTEXTURE;
    tags["mixBumpmap"] = EMIXBUMPMAP;
    tags["bumpmap"]    = EBUMPMAP;
    tags["emitter"]    = EEmitter;
    tags["camera"]     = ECamera;
    tags["medium"]     = EMedium;
    tags["volume"]     = EVolume;
    tags["phase"]      = EPhaseFunction;
    tags["integrator"] = EIntegrator;
    tags["sampler"]    = ESampler;
    tags["rfilter"]    = EReconstructionFilter;
    tags["test"]       = ETest;
    tags["boolean"]    = EBoolean;
    tags["integer"]    = EInteger;
    tags["float"]      = EFloat;
    tags["string"]     = EString;
    tags["point"]      = EPoint;
    tags["vector"]     = EVector;
    tags["color"]      = EColor;
    tags["transform"]  = ETransform;
    tags["translate"]  = ETranslate;
    tags["matrix"]     = EMatrix;
    tags["rotate"]     = ERotate;
    tags["scale"]      = EScale;
    tags["lookat"]     = ELookAt;

    /* Helper function to check if attributes are fully specified */
    auto check_attributes = [&](const pugi::xml_node &node, std::set<std::string> attrs) {
        for (auto attr : node.attributes()) {
            auto it = attrs.find(attr.name());
            if (it == attrs.end())
                throw NoriException("Error while parsing \"%s\": unexpected attribute \"%s\" in \"%s\" at %s",
                                    filename, attr.name(), node.name(), offset(node.offset_debug()));
            attrs.erase(it);
        }
        if (!attrs.empty())
            throw NoriException("Error while parsing \"%s\": missing attribute \"%s\" in \"%s\" at %s",
                                filename, *attrs.begin(), node.name(), offset(node.offset_debug()));
    };

    Eigen::Affine3f transform;

    /* Helper function to parse a Nori XML node (recursive) */
    std::function<NoriObject *(pugi::xml_node &, PropertyList &, int)> parseTag = [&](
    pugi::xml_node &node, PropertyList &list, int parentTag) -> NoriObject * {
        /* Skip over comments */
        if (node.type() == pugi::node_comment || node.type() == pugi::node_declaration)
            return nullptr;

        if (node.type() != pugi::node_element)
            throw NoriException(
                "Error while parsing \"%s\": unexpected content at %s",
                filename, offset(node.offset_debug()));

        /* Look up the name of the current element */
        auto it = tags.find(node.name());
        if (it == tags.end())
            throw NoriException("Error while parsing \"%s\": unexpected tag \"%s\" at %s",
            filename, node.name(), offset(node.offset_debug()));
        int tag = it->second;

        /* Perform some safety checks to make sure that the XML tree really makes sense */
        bool hasParent            = parentTag != EInvalid;
        bool parentIsObject       = hasParent && parentTag < NoriObject::EClassTypeCount;
        bool currentIsObject      = tag < NoriObject::EClassTypeCount;
        bool parentIsTransform    = parentTag == ETransform;
        bool currentIsTransformOp = tag == ETranslate || tag == ERotate || tag == EScale || tag == ELookAt || tag == EMatrix;

        if (!hasParent && !currentIsObject)
            throw NoriException("Error while parsing \"%s\": root element \"%s\" must be a Nori object (at %s)",
            filename, node.name(), offset(node.offset_debug()));

        if (parentIsTransform != currentIsTransformOp)
            throw NoriException("Error while parsing \"%s\": transform nodes "
            "can only contain transform operations (at %s)",
            filename,  offset(node.offset_debug()));

        if (hasParent && !parentIsObject && !(parentIsTransform && currentIsTransformOp))
            throw NoriException("Error while parsing \"%s\": node \"%s\" requires a Nori object as parent (at %s)",
            filename, node.name(), offset(node.offset_debug()));

        if (tag == EScene)
            node.append_attribute("type") = "scene";
        else if (tag == ETransform)
            transform.setIdentity();

        PropertyList propList;
        std::vector<NoriObject *> children;
        for (pugi::xml_node &ch: node.children()) {
            NoriObject *child = parseTag(ch, propList, tag);
            if (child)
                children.push_back(child);
        }

        NoriObject *result = nullptr;
        try {
            if (currentIsObject) {
                check_attributes(node, { "type" });

                /* This is an object, first instantiate it */
                result = NoriObjectFactory::createInstance(
                             node.attribute("type").value(),
                             propList
                         );

                if (result->getClassType() != (int) tag) {
                    throw NoriException(
                        "Unexpectedly constructed an object "
                        "of type <%s> (expected type <%s>): %s",
                        NoriObject::classTypeName(result->getClassType()),
                        NoriObject::classTypeName((NoriObject::EClassType) tag),
                        result->toString());
                }

                /* Add all children */
                for (auto ch: children) {
                    result->addChild(ch);
                    ch->setParent(result);
                }

                /* Activate / configure the object */
                result->activate();
            } else {
                /* This is a property */
                switch (tag) {
                case EString: {
                    check_attributes(node, { "name", "value" });
                    list.setString(node.attribute("name").value(), node.attribute("value").value());
                }
                break;
                case EFloat: {
                    check_attributes(node, { "name", "value" });
                    list.setFloat(node.attribute("name").value(), toFloat(node.attribute("value").value()));
                }
                break;
                case EInteger: {
                    check_attributes(node, { "name", "value" });
                    list.setInteger(node.attribute("name").value(), toInt(node.attribute("value").value()));
                }
                break;
                case EBoolean: {
                    check_attributes(node, { "name", "value" });
                    list.setBoolean(node.attribute("name").value(), toBool(node.attribute("value").value()));
                }
                break;
                case EPoint: {
                    check_attributes(node, { "name", "value" });
                    list.setPoint(node.attribute("name").value(), Point3f(toVector3f(node.attribute("value").value())));
                }
                break;
                case EVector: {
                    check_attributes(node, { "name", "value" });
                    list.setVector(node.attribute("name").value(), Vector3f(toVector3f(node.attribute("value").value())));
                }
                break;
                case EColor: {
                    check_attributes(node, { "name", "value" });
                    list.setColor(node.attribute("name").value(), Color3f(toVector3f(node.attribute("value").value()).array()));
                }
                break;
                case ETransform: {
                    check_attributes(node, { "name" });
                    list.setTransform(node.attribute("name").value(), transform.matrix());
                }
                break;
                case ETranslate: {
                    check_attributes(node, { "value" });
                    Eigen::Vector3f v = toVector3f(node.attribute("value").value());
                    transform = Eigen::Translation<float, 3>(v.x(), v.y(), v.z()) * transform;
                }
                break;
                case EMatrix: {
                    check_attributes(node, { "value" });
                    std::vector<std::string> tokens = tokenize(node.attribute("value").value());
                    if (tokens.size() != 16)
                        throw NoriException("Expected 16 values");
                    Eigen::Matrix4f matrix;
                    for (int i=0; i<4; ++i)
                        for (int j=0; j<4; ++j)
                            matrix(i, j) = toFloat(tokens[i*4+j]);
                    transform = Eigen::Affine3f(matrix) * transform;
                }
                break;
                case EScale: {
                    check_attributes(node, { "value" });
                    Eigen::Vector3f v = toVector3f(node.attribute("value").value());
                    transform = Eigen::DiagonalMatrix<float, 3>(v) * transform;
                }
                break;
                case ERotate: {
                    check_attributes(node, { "angle", "axis" });
                    float angle = degToRad(toFloat(node.attribute("angle").value()));
                    Eigen::Vector3f axis = toVector3f(node.attribute("axis").value());
                    transform = Eigen::AngleAxis<float>(angle, axis) * transform;
                }
                break;
                case ELookAt: {
                    check_attributes(node, { "origin", "target", "up" });
                    Eigen::Vector3f origin = toVector3f(node.attribute("origin").value());
                    Eigen::Vector3f target = toVector3f(node.attribute("target").value());
                    Eigen::Vector3f up = toVector3f(node.attribute("up").value());

                    Vector3f dir = (target - origin).normalized();
                    Vector3f left = up.normalized().cross(dir);
                    Vector3f newUp = dir.cross(left);

                    Eigen::Matrix4f trafo;
                    trafo << left, newUp, dir, origin,
                          0, 0, 0, 1;

                    transform = Eigen::Affine3f(trafo) * transform;
                }
                break;

                default:
                    throw NoriException("Unhandled element \"%s\"", node.name());
                };
            }
        } catch (const NoriException &e) {
            throw NoriException("Error while parsing \"%s\": %s (at %s)", filename,
                                e.what(), offset(node.offset_debug()));
        }

        return result;
    };

    PropertyList list;
    return parseTag(*doc.begin(), list, EInvalid);
}
Пример #16
0
	/// Sample the BRDF
	Color3f sample(BSDFQueryRecord &bRec, const Point2f &sample) const {
		throw NoriException("Uh oh -- Microfacet::sample() is not implemented!");
	}
Пример #17
0
	/// Evaluate the sampling density of \ref sample() wrt. solid angles
	float pdf(const BSDFQueryRecord &bRec) const {
		throw NoriException("Uh oh -- Microfacet::pdf() is not implemented!");
	}
Пример #18
0
	/// Evaluate the BRDF for the given pair of directions
	Color3f eval(const BSDFQueryRecord &bRec) const {
		throw NoriException("Uh oh -- Microfacet::eval() is not implemented!");
	}
Пример #19
0
	bool sampleDistance(const Ray3f &_ray, Sampler *sampler, float &t, Color3f &weight) const {
		/* Transform the ray into the local coordinate system */
		Ray3f ray = m_worldToMedium * _ray;

		throw NoriException("HeterogeneousMedium::sampleDistance(): not implemented!");
	}
Пример #20
0
    /// Invoke a series of t-tests on the provided input
    void activate() {
        int total = 0, passed = 0;
        pcg32 random;

        if (!m_bsdfs.empty()) {
            if (m_references.size() * m_bsdfs.size() != m_angles.size())
                throw NoriException("Specified a different number of angles and reference values!");
            if (!m_scenes.empty())
                throw NoriException("Cannot test BSDFs and scenes at the same time!");

            /* Test each registered BSDF */
            int ctr = 0;
            for (auto bsdf : m_bsdfs) {
                for (size_t i=0; i<m_references.size(); ++i) {
                    float angle = m_angles[i], reference = m_references[ctr++];

                    cout << "------------------------------------------------------" << endl;
                    cout << "Testing (angle=" << angle << "): " << bsdf->toString() << endl;
                    ++total;

                    BSDFQueryRecord bRec(sphericalDirection(degToRad(angle), 0));

                    cout << "Drawing " << m_sampleCount << " samples .. " << endl;
                    double mean=0, variance = 0;
                    for (int k=0; k<m_sampleCount; ++k) {
                        Point2f sample(random.nextFloat(), random.nextFloat());
                        double result = (double) bsdf->sample(bRec, sample).getLuminance();

                        /* Numerically robust online variance estimation using an
                           algorithm proposed by Donald Knuth (TAOCP vol.2, 3rd ed., p.232) */
                        double delta = result - mean;
                        mean += delta / (double) (k+1);
                        variance += delta * (result - mean);
                    }
                    variance /= m_sampleCount - 1;
                    std::pair<bool, std::string>
                        result = hypothesis::students_t_test(mean, variance, reference,
                            m_sampleCount, m_significanceLevel, (int) m_references.size());

                    if (result.first)
                        ++passed;
                    cout << result.second << endl;
                }
            }
        } else {
            if (m_references.size() != m_scenes.size())
                throw NoriException("Specified a different number of scenes and reference values!");

            Sampler *sampler = static_cast<Sampler *>(
                NoriObjectFactory::createInstance("independent", PropertyList()));

            int ctr = 0;
            for (auto scene : m_scenes) {
                const Integrator *integrator = scene->getIntegrator();
                const Camera *camera = scene->getCamera();
                float reference = m_references[ctr++];

                cout << "------------------------------------------------------" << endl;
                cout << "Testing scene: " << scene->toString() << endl;
                ++total;

                cout << "Generating " << m_sampleCount << " paths.. " << endl;

                double mean = 0, variance = 0;
                for (int k=0; k<m_sampleCount; ++k) {
                    /* Sample a ray from the camera */
                    Ray3f ray;
                    Point2f pixelSample = (sampler->next2D().array()
                        * camera->getOutputSize().cast<float>().array()).matrix();
                    Color3f value = camera->sampleRay(ray, pixelSample, sampler->next2D());

                    /* Compute the incident radiance */
                    value *= integrator->Li(scene, sampler, ray);

                    /* Numerically robust online variance estimation using an
                       algorithm proposed by Donald Knuth (TAOCP vol.2, 3rd ed., p.232) */
                    double result = (double) value.getLuminance();
                    double delta = result - mean;
                    mean += delta / (double) (k+1);
                    variance += delta * (result - mean);
                }
                variance /= m_sampleCount - 1;

                std::pair<bool, std::string>
                    result = hypothesis::students_t_test(mean, variance, reference,
                        m_sampleCount, m_significanceLevel, (int) m_references.size());

                if (result.first)
                    ++passed;
                cout << result.second << endl;
            }
        }
        cout << "Passed " << passed << "/" << total << " tests." << endl;
    }