<commit_before>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013, 2014 JCube001

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

#include <math.h>
#include "imu_filter.h"
#include "quaternion.h"

IMUFilter::IMUFilter() :
    Filter()
{
}

void IMUFilter::update(float wx, float wy, float wz,
                       float ax, float ay, float az)
{
    // The direction of gravity in the earth frame
    static const Quaternion Eg_hat(0.0f, 0.0f, 0.0f, 1.0f);

    // Compute the objective function
    const Quaternion f_g = SEq_hat.conjugate() * Eg_hat * SEq_hat - Quaternion(0.0f, ax, ay, az).normalized();

    // Compute the Jacobian matrix
    // Negative elements are negated in matrix multiplication
    const Quaternion two_SEq = 2.0f * SEq_hat;
    const float J_11_or_24 = two_SEq.y;
    const float J_12_or_23 = two_SEq.z;
    const float J_13_or_22 = two_SEq.w;
    const float J_14_or_21 = two_SEq.x;
    const float J_32 = 2.0f * J_14_or_21;
    const float J_33 = 2.0f * J_11_or_24;

    // Compute the normalized gradient descent (matrix multiplication)
    const Quaternion SEq_hat_dot
            = Quaternion(J_14_or_21 * f_g.y - J_11_or_24 * f_g.x,
                         J_12_or_23 * f_g.x + J_13_or_22 * f_g.y - J_32 * f_g.z,
                         J_12_or_23 * f_g.y - J_33 * f_g.z - J_13_or_22 * f_g.x,
                         J_14_or_21 * f_g.x + J_11_or_24 * f_g.y).normalized();

    // Compute the quaternion derivative measured by the gyroscope
    const Quaternion SEq_dot_omega = 0.5f * SEq_hat * Quaternion(0.0f, wx, wy, wz);

    // Compute then integrate the estimated quaternion derivative
    SEq_hat += (SEq_dot_omega - (beta * SEq_hat_dot)) * deltaTime;

    // Normalize the output quaternion
    SEq_hat.normalize();
}

<commit_msg>Moved code around<commit_after>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013, 2014 JCube001

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

#include <math.h>
#include "imu_filter.h"
#include "quaternion.h"

IMUFilter::IMUFilter() :
    Filter()
{
}

void IMUFilter::update(float wx, float wy, float wz,
                       float ax, float ay, float az)
{
    // Auxiliary variables to avoid repeated calculations
    const Quaternion two_SEq = 2.0f * SEq_hat;

    // Compute the objective function
    const Quaternion f_g = SEq_hat.conjugate() * Eg_hat * SEq_hat
            - Quaternion(0.0f, ax, ay, az).normalized();

    // Compute the Jacobian matrix
    // Negative elements are negated in matrix multiplication
    const float J_11_or_24 = two_SEq.y;
    const float J_12_or_23 = two_SEq.z;
    const float J_13_or_22 = two_SEq.w;
    const float J_14_or_21 = two_SEq.x;
    const float J_32 = 2.0f * J_14_or_21;
    const float J_33 = 2.0f * J_11_or_24;

    // Compute the normalized gradient descent (matrix multiplication)
    const Quaternion SEq_hat_dot
            = Quaternion(J_14_or_21 * f_g.y - J_11_or_24 * f_g.x,
                         J_12_or_23 * f_g.x + J_13_or_22 * f_g.y - J_32 * f_g.z,
                         J_12_or_23 * f_g.y - J_33 * f_g.z - J_13_or_22 * f_g.x,
                         J_14_or_21 * f_g.x + J_11_or_24 * f_g.y).normalized();

    // Compute the quaternion derivative measured by the gyroscope
    const Quaternion SEq_dot_omega = 0.5f * SEq_hat * Quaternion(0.0f, wx, wy, wz);

    // Compute then integrate the estimated quaternion derivative
    SEq_hat += (SEq_dot_omega - (beta * SEq_hat_dot)) * deltaTime;

    // Normalize the output quaternion
    SEq_hat.normalize();
}

<|endoftext|>


<commit_before>#include <signal.h>
#include <unistd.h>

#include <event/event_callback.h>
#include <event/event_thread.h>

static void signal_reload(int);

EventThread::EventThread(void)
: Thread("EventThread"),
  log_("/event/thread"),
  queue_(),
  reload_(),
  interest_queue_(),
  timeout_queue_(),
  poll_()
{
	INFO(log_) << "Starting event thread.";

	signal(SIGHUP, signal_reload);
}

void
EventThread::main(void)
{
	for (;;) {
		/*
		 * If we have been told to stop, fire all shutdown events.
		 */
		if (stop_ && !interest_queue_[EventInterestStop].empty()) {
			INFO(log_) << "Running stop handlers.";
			if (interest_queue_[EventInterestStop].drain())
				ERROR(log_) << "Stop handlers added other stop handlers.";
			INFO(log_) << "Stop handlers have been run.";
		}

		/*
		 * If we have been told to reload, fire all shutdown events.
		 */
		if (reload_ && !interest_queue_[EventInterestReload].empty()) {
			INFO(log_) << "Running reload handlers.";
			interest_queue_[EventInterestReload].drain();
			INFO(log_) << "Reload handlers have been run.";

			reload_ = false;
			signal(SIGHUP, signal_reload);
		}

		/*
		 * If there are time-triggered events whose time has come,
		 * run them.
		 */
		if (!timeout_queue_.empty()) {
			while (timeout_queue_.ready())
				timeout_queue_.perform();
		}

		/*
		 * And then run a pending callback.
		 */
		while (!queue_.empty() && !timeout_queue_.ready()) {
			queue_.perform();
			if (stop_ || reload_)
				break;
			/*
			 * Quickly poll in between callbacks in case there are
			 * a lot of callbacks or an infinite number of
			 * callbacks, so that we can still handle I/O.
			 */
			if (!poll_.idle())
				poll_.poll();
		}

		/*
		 * If there are any pending callbacks, go back to the start
		 * of the loop.
		 */
		if (!queue_.empty() || timeout_queue_.ready())
			continue;

		/*
		 * But if there are no pending callbacks, and no timers or
		 * file descriptors being polled, stop.
		 */
		if (timeout_queue_.empty() && poll_.idle())
			break;
		/*
		 * If there are timers ticking down, then let the poll module
		 * block until a timer will be ready.
		 * XXX Maybe block 1 second less, just in case?  We'll never
		 * be a realtime thread though, so any attempt at pretending
		 * to be one, beyond giving time events priority at the top of
		 * this loop, is probably a mistake.
		 */
		if (!timeout_queue_.empty()) {
			poll_.wait(timeout_queue_.interval());
			continue;
		}
		/*
		 * If, however, there's nothing sensitive to time, but someone
		 * has a file descriptor that can be blocked on, just block on it
		 * indefinitely.
		 */
		poll_.wait();
	}
}

void
EventThread::reload(void)
{
	signal(SIGHUP, SIG_IGN);
	INFO(log_) << "Running reload events.";
	reload_ = true;
}

static void
signal_reload(int)
{
	EventThread::self()->reload();
	/* XXX Forward signal to all threads.  */
}
<commit_msg>Use namespace{}.<commit_after>#include <signal.h>
#include <unistd.h>

#include <event/event_callback.h>
#include <event/event_thread.h>

namespace {
	static void signal_reload(int);
}

EventThread::EventThread(void)
: Thread("EventThread"),
  log_("/event/thread"),
  queue_(),
  reload_(),
  interest_queue_(),
  timeout_queue_(),
  poll_()
{
	INFO(log_) << "Starting event thread.";

	signal(SIGHUP, signal_reload);
}

void
EventThread::main(void)
{
	for (;;) {
		/*
		 * If we have been told to stop, fire all shutdown events.
		 */
		if (stop_ && !interest_queue_[EventInterestStop].empty()) {
			INFO(log_) << "Running stop handlers.";
			if (interest_queue_[EventInterestStop].drain())
				ERROR(log_) << "Stop handlers added other stop handlers.";
			INFO(log_) << "Stop handlers have been run.";
		}

		/*
		 * If we have been told to reload, fire all shutdown events.
		 */
		if (reload_ && !interest_queue_[EventInterestReload].empty()) {
			INFO(log_) << "Running reload handlers.";
			interest_queue_[EventInterestReload].drain();
			INFO(log_) << "Reload handlers have been run.";

			reload_ = false;
			signal(SIGHUP, signal_reload);
		}

		/*
		 * If there are time-triggered events whose time has come,
		 * run them.
		 */
		if (!timeout_queue_.empty()) {
			while (timeout_queue_.ready())
				timeout_queue_.perform();
		}

		/*
		 * And then run a pending callback.
		 */
		while (!queue_.empty() && !timeout_queue_.ready()) {
			queue_.perform();
			if (stop_ || reload_)
				break;
			/*
			 * Quickly poll in between callbacks in case there are
			 * a lot of callbacks or an infinite number of
			 * callbacks, so that we can still handle I/O.
			 */
			if (!poll_.idle())
				poll_.poll();
		}

		/*
		 * If there are any pending callbacks, go back to the start
		 * of the loop.
		 */
		if (!queue_.empty() || timeout_queue_.ready())
			continue;

		/*
		 * But if there are no pending callbacks, and no timers or
		 * file descriptors being polled, stop.
		 */
		if (timeout_queue_.empty() && poll_.idle())
			break;
		/*
		 * If there are timers ticking down, then let the poll module
		 * block until a timer will be ready.
		 * XXX Maybe block 1 second less, just in case?  We'll never
		 * be a realtime thread though, so any attempt at pretending
		 * to be one, beyond giving time events priority at the top of
		 * this loop, is probably a mistake.
		 */
		if (!timeout_queue_.empty()) {
			poll_.wait(timeout_queue_.interval());
			continue;
		}
		/*
		 * If, however, there's nothing sensitive to time, but someone
		 * has a file descriptor that can be blocked on, just block on it
		 * indefinitely.
		 */
		poll_.wait();
	}
}

void
EventThread::reload(void)
{
	signal(SIGHUP, SIG_IGN);
	INFO(log_) << "Running reload events.";
	reload_ = true;
}

namespace {
	static void
	signal_reload(int)
	{
		EventThread::self()->reload();
		/* XXX Forward signal to all threads.  */
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <string.h>
#include <limits.h>

#include "buffers.h"
#include "camera.h"
#include "device.h"
#include "scene.h"
#include "session.h"

#include "util_foreach.h"
#include "util_function.h"
#include "util_time.h"

CCL_NAMESPACE_BEGIN

Session::Session(const SessionParams& params_)
: params(params_),
  tile_manager(params.progressive, params.passes, params.tile_size, params.min_size)
{
	device_use_gl = (params.device_type == DEVICE_CUDA && !params.background);

	device = Device::create(params.device_type, params.background, params.threads);
	buffers = new RenderBuffers(device);
	display = new DisplayBuffer(device);

	session_thread = NULL;
	scene = NULL;

	start_time = 0.0;
	reset_time = 0.0;
	preview_time = 0.0;
	pass = 0;

	delayed_reset.do_reset = false;
	delayed_reset.w = 0;
	delayed_reset.h = 0;
	delayed_reset.passes = 0;

	display_outdated = false;
	gpu_draw_ready = false;
	gpu_need_tonemap = false;
	pause = false;
}

Session::~Session()
{
	if(session_thread) {
		progress.set_cancel("Exiting");
		gpu_need_tonemap = false;
		gpu_need_tonemap_cond.notify_all();
		set_pause(false);
		wait();
	}

	if(params.output_path != "") {
		progress.set_status("Writing Image", params.output_path);
		display->write(device, params.output_path);
	}

	delete buffers;
	delete display;
	delete scene;
	delete device;
}

void Session::start()
{
	session_thread = new thread(function_bind(&Session::run, this));
}

bool Session::ready_to_reset()
{
	double dt = time_dt() - reset_time;

	if(!display_outdated)
		return (dt > params.reset_timeout);
	else
		return (dt > params.cancel_timeout);
}

/* GPU Session */

void Session::reset_gpu(int w, int h, int passes)
{
	/* block for buffer acces and reset immediately. we can't do this
	   in the thread, because we need to allocate an OpenGL buffer, and
	   that only works in the main thread */
	thread_scoped_lock display_lock(display->mutex);
	thread_scoped_lock buffers_lock(buffers->mutex);

	display_outdated = true;
	reset_time = time_dt();

	reset_(w, h, passes);

	gpu_need_tonemap = false;
	gpu_need_tonemap_cond.notify_all();

	pause_cond.notify_all();
}

bool Session::draw_gpu(int w, int h)
{
	/* block for buffer access */
	thread_scoped_lock display_lock(display->mutex);

	/* first check we already rendered something */
	if(gpu_draw_ready) {
		/* then verify the buffers have the expected size, so we don't
		   draw previous results in a resized window */
		if(w == display->width && h == display->height) {
			/* for CUDA we need to do tonemapping still, since we can
			   only access GL buffers from the main thread */
			if(gpu_need_tonemap) {
				thread_scoped_lock buffers_lock(buffers->mutex);
				tonemap();
				gpu_need_tonemap = false;
				gpu_need_tonemap_cond.notify_all();
			}

			display->draw(device);

			if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
				return false;

			return true;
		}
	}

	return false;
}

void Session::run_gpu()
{
	start_time = time_dt();
	reset_time = time_dt();

	while(!progress.get_cancel()) {
		/* advance to next tile */
		bool done = !tile_manager.next();

		/* any work left? */
		if(done) {
			/* if in background mode, we can stop immediately */
			if(params.background) {
				break;
			}
			else {
				/* in interactive mode, we wait until woken up */
				thread_scoped_lock pause_lock(pause_mutex);
				pause_cond.wait(pause_lock);
			}
		}
		else {
			/* test for pause and wait until woken up */
			thread_scoped_lock pause_lock(pause_mutex);
			while(pause)
				pause_cond.wait(pause_lock);
		}

		{
			/* buffers mutex is locked entirely while rendering each
			   pass, and released/reacquired on each iteration to allow
			   reset and draw in between */
			thread_scoped_lock buffers_lock(buffers->mutex);

			/* update scene */
			update_scene();
			if(progress.get_cancel())
				break;

			/* update status and timing */
			update_status_time();

			/* path trace */
			foreach(Tile& tile, tile_manager.state.tiles) {
				path_trace(tile);

				device->task_wait();

				if(progress.get_cancel())
					break;
			}

			/* update status and timing */
			update_status_time();

			gpu_need_tonemap = true;
			gpu_draw_ready = true;
			progress.set_update();

			/* wait for tonemap */
			if(!params.background) {
				while(gpu_need_tonemap) {
					if(progress.get_cancel())
						break;

					gpu_need_tonemap_cond.wait(buffers_lock);
				}
			}

			if(progress.get_cancel())
				break;
		}
	}
}

/* CPU Session */

void Session::reset_cpu(int w, int h, int passes)
{
	thread_scoped_lock reset_lock(delayed_reset.mutex);

	display_outdated = true;
	reset_time = time_dt();

	delayed_reset.w = w;
	delayed_reset.h = h;
	delayed_reset.passes = passes;
	delayed_reset.do_reset = true;
	device->task_cancel();

	pause_cond.notify_all();
}

bool Session::draw_cpu(int w, int h)
{
	thread_scoped_lock display_lock(display->mutex);

	/* first check we already rendered something */
	if(display->draw_ready()) {
		/* then verify the buffers have the expected size, so we don't
		   draw previous results in a resized window */
		if(w == display->width && h == display->height) {
			display->draw(device);

			if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
				return false;

			return true;
		}
	}

	return false;
}

void Session::run_cpu()
{
	{
		/* reset once to start */
		thread_scoped_lock reset_lock(delayed_reset.mutex);
		thread_scoped_lock buffers_lock(buffers->mutex);
		thread_scoped_lock display_lock(display->mutex);

		reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes);
		delayed_reset.do_reset = false;
	}

	while(!progress.get_cancel()) {
		/* advance to next tile */
		bool done = !tile_manager.next();
		bool need_tonemap = false;

		/* any work left? */
		if(done) {
			/* if in background mode, we can stop immediately */
			if(params.background) {
				break;
			}
			else {
				/* in interactive mode, we wait until woken up */
				thread_scoped_lock pause_lock(pause_mutex);
				pause_cond.wait(pause_lock);
			}
		}
		else {
			/* test for pause and wait until woken up */
			thread_scoped_lock pause_lock(pause_mutex);
			while(pause)
				pause_cond.wait(pause_lock);
		}

		if(!done) {
			/* buffers mutex is locked entirely while rendering each
			   pass, and released/reacquired on each iteration to allow
			   reset and draw in between */
			thread_scoped_lock buffers_lock(buffers->mutex);

			/* update scene */
			update_scene();
			if(progress.get_cancel())
				break;

			/* update status and timing */
			update_status_time();

			/* path trace */
			foreach(Tile& tile, tile_manager.state.tiles)
				path_trace(tile);

			/* update status and timing */
			update_status_time();

			need_tonemap = true;
		}

		device->task_wait();

		{
			thread_scoped_lock reset_lock(delayed_reset.mutex);
			thread_scoped_lock buffers_lock(buffers->mutex);
			thread_scoped_lock display_lock(display->mutex);

			if(delayed_reset.do_reset) {
				/* reset rendering if request from main thread */
				delayed_reset.do_reset = false;
				reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes);
			}
			else if(need_tonemap) {
				/* tonemap only if we do not reset, we don't we don't
				   want to show the result of an incomplete pass*/
				tonemap();
			}
		}

		progress.set_update();
	}
}

void Session::run()
{
	/* session thread loop */
	progress.set_status("Waiting for render to start");

	/* first scene update */
	if(!progress.get_cancel()) {
		thread_scoped_lock scene_lock(scene->mutex);
		scene->device_update(device, progress);
	}

	/* run */
	if(!progress.get_cancel()) {
		if(device_use_gl)
			run_gpu();
		else
			run_cpu();
	}

	/* progress update */
	if(progress.get_cancel())
		progress.set_status(progress.get_cancel_message());
	else
		progress.set_update();
}

bool Session::draw(int w, int h)
{
	if(device_use_gl)
		return draw_gpu(w, h);
	else
		return draw_cpu(w, h);
}

void Session::reset_(int w, int h, int passes)
{
	if(w != buffers->width || h != buffers->height) {
		gpu_draw_ready = false;
		buffers->reset(device, w, h);
		display->reset(device, w, h);
	}

	tile_manager.reset(w, h, passes);

	start_time = time_dt();
	preview_time = 0.0;
	pass = 0;
}

void Session::reset(int w, int h, int passes)
{
	if(device_use_gl)
		reset_gpu(w, h, passes);
	else
		reset_cpu(w, h, passes);
}

void Session::set_passes(int passes)
{
	if(passes != params.passes) {
		params.passes = passes;
		tile_manager.set_passes(passes);

		pause_cond.notify_all();
	}
}

void Session::set_pause(bool pause_)
{
	{
		thread_scoped_lock pause_lock(pause_mutex);
		pause = pause_;
	}

	pause_cond.notify_all();
}

void Session::wait()
{
	session_thread->join();
	delete session_thread;

	session_thread = NULL;
}

void Session::update_scene()
{
	thread_scoped_lock scene_lock(scene->mutex);

	progress.set_status("Updating Scene");

	/* update camera if dimensions changed for progressive render */
	Camera *cam = scene->camera;
	int w = tile_manager.state.width;
	int h = tile_manager.state.height;

	if(cam->width != w || cam->height != h) {
		cam->width = w;
		cam->height = h;
		cam->tag_update();
	}

	/* update scene */
	if(scene->need_update())
		scene->device_update(device, progress);
}

void Session::update_status_time()
{
	int pass = tile_manager.state.pass;
	int resolution = tile_manager.state.resolution;

	/* update status */
	string substatus;
	if(!params.progressive)
		substatus = "Path Tracing";
	else if(params.passes == INT_MAX)
		substatus = string_printf("Path Tracing Pass %d", pass+1);
	else
		substatus = string_printf("Path Tracing Pass %d/%d", pass+1, params.passes);
	progress.set_status("Rendering", substatus);

	/* update timing */
	if(preview_time == 0.0 && resolution == 1)
		preview_time = time_dt();

	double total_time = (time_dt() - start_time);
	double pass_time = (pass == 0)? 0.0: (time_dt() - preview_time)/(pass);

	progress.set_pass(pass + 1, total_time, pass_time);
}

void Session::path_trace(Tile& tile)
{
	/* add path trace task */
	DeviceTask task(DeviceTask::PATH_TRACE);

	task.x = tile.x;
	task.y = tile.y;
	task.w = tile.w;
	task.h = tile.h;
	task.buffer = buffers->buffer.device_pointer;
	task.rng_state = buffers->rng_state.device_pointer;
	task.pass = tile_manager.state.pass;
	task.resolution = tile_manager.state.resolution;

	device->task_add(task);
}

void Session::tonemap()
{
	/* add tonemap task */
	DeviceTask task(DeviceTask::TONEMAP);

	task.x = 0;
	task.y = 0;
	task.w = tile_manager.state.width;
	task.h = tile_manager.state.height;
	task.rgba = display->rgba.device_pointer;
	task.buffer = buffers->buffer.device_pointer;
	task.pass = tile_manager.state.pass;
	task.resolution = tile_manager.state.resolution;

	device->task_add(task);
	device->task_wait();

	/* set display to new size */
	display->draw_set(tile_manager.state.width, tile_manager.state.height);

	display_outdated = false;
}

CCL_NAMESPACE_END

<commit_msg>Cycles: fix cuda assertion that could be triggerd sometimes, when trying to tonemap an empty image.<commit_after>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <string.h>
#include <limits.h>

#include "buffers.h"
#include "camera.h"
#include "device.h"
#include "scene.h"
#include "session.h"

#include "util_foreach.h"
#include "util_function.h"
#include "util_time.h"

CCL_NAMESPACE_BEGIN

Session::Session(const SessionParams& params_)
: params(params_),
  tile_manager(params.progressive, params.passes, params.tile_size, params.min_size)
{
	device_use_gl = (params.device_type == DEVICE_CUDA && !params.background);

	device = Device::create(params.device_type, params.background, params.threads);
	buffers = new RenderBuffers(device);
	display = new DisplayBuffer(device);

	session_thread = NULL;
	scene = NULL;

	start_time = 0.0;
	reset_time = 0.0;
	preview_time = 0.0;
	pass = 0;

	delayed_reset.do_reset = false;
	delayed_reset.w = 0;
	delayed_reset.h = 0;
	delayed_reset.passes = 0;

	display_outdated = false;
	gpu_draw_ready = false;
	gpu_need_tonemap = false;
	pause = false;
}

Session::~Session()
{
	if(session_thread) {
		progress.set_cancel("Exiting");
		gpu_need_tonemap = false;
		gpu_need_tonemap_cond.notify_all();
		set_pause(false);
		wait();
	}

	if(params.output_path != "") {
		progress.set_status("Writing Image", params.output_path);
		display->write(device, params.output_path);
	}

	delete buffers;
	delete display;
	delete scene;
	delete device;
}

void Session::start()
{
	session_thread = new thread(function_bind(&Session::run, this));
}

bool Session::ready_to_reset()
{
	double dt = time_dt() - reset_time;

	if(!display_outdated)
		return (dt > params.reset_timeout);
	else
		return (dt > params.cancel_timeout);
}

/* GPU Session */

void Session::reset_gpu(int w, int h, int passes)
{
	/* block for buffer acces and reset immediately. we can't do this
	   in the thread, because we need to allocate an OpenGL buffer, and
	   that only works in the main thread */
	thread_scoped_lock display_lock(display->mutex);
	thread_scoped_lock buffers_lock(buffers->mutex);

	display_outdated = true;
	reset_time = time_dt();

	reset_(w, h, passes);

	gpu_need_tonemap = false;
	gpu_need_tonemap_cond.notify_all();

	pause_cond.notify_all();
}

bool Session::draw_gpu(int w, int h)
{
	/* block for buffer access */
	thread_scoped_lock display_lock(display->mutex);

	/* first check we already rendered something */
	if(gpu_draw_ready) {
		/* then verify the buffers have the expected size, so we don't
		   draw previous results in a resized window */
		if(w == display->width && h == display->height) {
			/* for CUDA we need to do tonemapping still, since we can
			   only access GL buffers from the main thread */
			if(gpu_need_tonemap) {
				thread_scoped_lock buffers_lock(buffers->mutex);
				tonemap();
				gpu_need_tonemap = false;
				gpu_need_tonemap_cond.notify_all();
			}

			display->draw(device);

			if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
				return false;

			return true;
		}
	}

	return false;
}

void Session::run_gpu()
{
	start_time = time_dt();
	reset_time = time_dt();

	while(!progress.get_cancel()) {
		/* advance to next tile */
		bool done = !tile_manager.next();

		/* any work left? */
		if(done) {
			/* if in background mode, we can stop immediately */
			if(params.background) {
				break;
			}
			else {
				/* in interactive mode, we wait until woken up */
				thread_scoped_lock pause_lock(pause_mutex);
				pause_cond.wait(pause_lock);
			}
		}
		else {
			/* test for pause and wait until woken up */
			thread_scoped_lock pause_lock(pause_mutex);
			while(pause)
				pause_cond.wait(pause_lock);
		}

		{
			/* buffers mutex is locked entirely while rendering each
			   pass, and released/reacquired on each iteration to allow
			   reset and draw in between */
			thread_scoped_lock buffers_lock(buffers->mutex);

			/* update scene */
			update_scene();
			if(progress.get_cancel())
				break;

			/* update status and timing */
			update_status_time();

			/* path trace */
			foreach(Tile& tile, tile_manager.state.tiles) {
				path_trace(tile);

				device->task_wait();

				if(progress.get_cancel())
					break;
			}

			/* update status and timing */
			update_status_time();

			gpu_need_tonemap = true;
			gpu_draw_ready = true;
			progress.set_update();

			/* wait for tonemap */
			if(!params.background) {
				while(gpu_need_tonemap) {
					if(progress.get_cancel())
						break;

					gpu_need_tonemap_cond.wait(buffers_lock);
				}
			}

			if(progress.get_cancel())
				break;
		}
	}
}

/* CPU Session */

void Session::reset_cpu(int w, int h, int passes)
{
	thread_scoped_lock reset_lock(delayed_reset.mutex);

	display_outdated = true;
	reset_time = time_dt();

	delayed_reset.w = w;
	delayed_reset.h = h;
	delayed_reset.passes = passes;
	delayed_reset.do_reset = true;
	device->task_cancel();

	pause_cond.notify_all();
}

bool Session::draw_cpu(int w, int h)
{
	thread_scoped_lock display_lock(display->mutex);

	/* first check we already rendered something */
	if(display->draw_ready()) {
		/* then verify the buffers have the expected size, so we don't
		   draw previous results in a resized window */
		if(w == display->width && h == display->height) {
			display->draw(device);

			if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
				return false;

			return true;
		}
	}

	return false;
}

void Session::run_cpu()
{
	{
		/* reset once to start */
		thread_scoped_lock reset_lock(delayed_reset.mutex);
		thread_scoped_lock buffers_lock(buffers->mutex);
		thread_scoped_lock display_lock(display->mutex);

		reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes);
		delayed_reset.do_reset = false;
	}

	while(!progress.get_cancel()) {
		/* advance to next tile */
		bool done = !tile_manager.next();
		bool need_tonemap = false;

		/* any work left? */
		if(done) {
			/* if in background mode, we can stop immediately */
			if(params.background) {
				break;
			}
			else {
				/* in interactive mode, we wait until woken up */
				thread_scoped_lock pause_lock(pause_mutex);
				pause_cond.wait(pause_lock);
			}
		}
		else {
			/* test for pause and wait until woken up */
			thread_scoped_lock pause_lock(pause_mutex);
			while(pause)
				pause_cond.wait(pause_lock);
		}

		if(!done) {
			/* buffers mutex is locked entirely while rendering each
			   pass, and released/reacquired on each iteration to allow
			   reset and draw in between */
			thread_scoped_lock buffers_lock(buffers->mutex);

			/* update scene */
			update_scene();
			if(progress.get_cancel())
				break;

			/* update status and timing */
			update_status_time();

			/* path trace */
			foreach(Tile& tile, tile_manager.state.tiles)
				path_trace(tile);

			/* update status and timing */
			update_status_time();

			need_tonemap = true;
		}

		device->task_wait();

		{
			thread_scoped_lock reset_lock(delayed_reset.mutex);
			thread_scoped_lock buffers_lock(buffers->mutex);
			thread_scoped_lock display_lock(display->mutex);

			if(delayed_reset.do_reset) {
				/* reset rendering if request from main thread */
				delayed_reset.do_reset = false;
				reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes);
			}
			else if(need_tonemap) {
				/* tonemap only if we do not reset, we don't we don't
				   want to show the result of an incomplete pass*/
				tonemap();
			}
		}

		progress.set_update();
	}
}

void Session::run()
{
	/* session thread loop */
	progress.set_status("Waiting for render to start");

	/* first scene update */
	if(!progress.get_cancel()) {
		thread_scoped_lock scene_lock(scene->mutex);
		scene->device_update(device, progress);
	}

	/* run */
	if(!progress.get_cancel()) {
		if(device_use_gl)
			run_gpu();
		else
			run_cpu();
	}

	/* progress update */
	if(progress.get_cancel())
		progress.set_status(progress.get_cancel_message());
	else
		progress.set_update();
}

bool Session::draw(int w, int h)
{
	if(device_use_gl)
		return draw_gpu(w, h);
	else
		return draw_cpu(w, h);
}

void Session::reset_(int w, int h, int passes)
{
	if(w != buffers->width || h != buffers->height) {
		gpu_draw_ready = false;
		buffers->reset(device, w, h);
		display->reset(device, w, h);
	}

	tile_manager.reset(w, h, passes);

	start_time = time_dt();
	preview_time = 0.0;
	pass = 0;
}

void Session::reset(int w, int h, int passes)
{
	if(device_use_gl)
		reset_gpu(w, h, passes);
	else
		reset_cpu(w, h, passes);
}

void Session::set_passes(int passes)
{
	if(passes != params.passes) {
		params.passes = passes;
		tile_manager.set_passes(passes);

		pause_cond.notify_all();
	}
}

void Session::set_pause(bool pause_)
{
	{
		thread_scoped_lock pause_lock(pause_mutex);
		pause = pause_;
	}

	pause_cond.notify_all();
}

void Session::wait()
{
	session_thread->join();
	delete session_thread;

	session_thread = NULL;
}

void Session::update_scene()
{
	thread_scoped_lock scene_lock(scene->mutex);

	progress.set_status("Updating Scene");

	/* update camera if dimensions changed for progressive render */
	Camera *cam = scene->camera;
	int w = tile_manager.state.width;
	int h = tile_manager.state.height;

	if(cam->width != w || cam->height != h) {
		cam->width = w;
		cam->height = h;
		cam->tag_update();
	}

	/* update scene */
	if(scene->need_update())
		scene->device_update(device, progress);
}

void Session::update_status_time()
{
	int pass = tile_manager.state.pass;
	int resolution = tile_manager.state.resolution;

	/* update status */
	string substatus;
	if(!params.progressive)
		substatus = "Path Tracing";
	else if(params.passes == INT_MAX)
		substatus = string_printf("Path Tracing Pass %d", pass+1);
	else
		substatus = string_printf("Path Tracing Pass %d/%d", pass+1, params.passes);
	progress.set_status("Rendering", substatus);

	/* update timing */
	if(preview_time == 0.0 && resolution == 1)
		preview_time = time_dt();

	double total_time = (time_dt() - start_time);
	double pass_time = (pass == 0)? 0.0: (time_dt() - preview_time)/(pass);

	progress.set_pass(pass + 1, total_time, pass_time);
}

void Session::path_trace(Tile& tile)
{
	/* add path trace task */
	DeviceTask task(DeviceTask::PATH_TRACE);

	task.x = tile.x;
	task.y = tile.y;
	task.w = tile.w;
	task.h = tile.h;
	task.buffer = buffers->buffer.device_pointer;
	task.rng_state = buffers->rng_state.device_pointer;
	task.pass = tile_manager.state.pass;
	task.resolution = tile_manager.state.resolution;

	device->task_add(task);
}

void Session::tonemap()
{
	/* add tonemap task */
	DeviceTask task(DeviceTask::TONEMAP);

	task.x = 0;
	task.y = 0;
	task.w = tile_manager.state.width;
	task.h = tile_manager.state.height;
	task.rgba = display->rgba.device_pointer;
	task.buffer = buffers->buffer.device_pointer;
	task.pass = tile_manager.state.pass;
	task.resolution = tile_manager.state.resolution;

	if(task.w > 0 && task.h > 0) {
		device->task_add(task);
		device->task_wait();

		/* set display to new size */
		display->draw_set(task.w, task.h);
	}

	display_outdated = false;
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>/* COPYRIGHT (c) 2015 Sam Westrick, Laxman Dhulipala, Umut Acar,
 * Arthur Chargueraud, and Michael Rainey.
 * All rights reserved.
 *
 * \file pwsa.cpp
 */
#include "benchmark.hpp"
#include "pwsa.hpp"
#include "sam_bin_heap.hpp"
#include "weighted_graph.hpp"
//include "bin_heap.hpp"
//include "treap-frontier.hpp"
//include <math.h>

int main(int argc, char** argv) {
  int split_cutoff; // (K)
  int poll_cutoff; // (D)
  std::string fname;
  int srow;
  int scol;
  int drow;
  int dcol;
  double w;
  double exptime;
  bool debug;

  Graph G;
  int src;
  int dst;

  std::atomic<int>* res;

  auto init = [&] {
    split_cutoff = (int)pasl::util::cmdline::parse_or_default_int("K", 10000);
    poll_cutoff = (int)pasl::util::cmdline::parse_or_default_int("D", 10000);
    fname = pasl::util::cmdline::parse_or_default_string("map", "maps/simple_map.map");
    srow = (int)pasl::util::cmdline::parse_or_default_int("sr", 1);
    scol = (int)pasl::util::cmdline::parse_or_default_int("sc", 1);
    drow = (int)pasl::util::cmdline::parse_or_default_int("dr", 1);
    dcol = (int)pasl::util::cmdline::parse_or_default_int("dc", 1);
    w = (double)pasl::util::cmdline::parse_or_default_float("w", 1.0);
    exptime = (double)pasl::util::cmdline::parse_or_default_float("exptime", 0.0000000001);
    debug = pasl::util::cmdline::parse_or_default_bool("debug", false);

    G = Graph(fname.c_str());

    src = G.vertex_at(srow, scol);
    dst = G.vertex_at(drow, dcol);
  };

  auto run = [&] (bool sequential) {
    auto heuristic = [&] (int v) {
      return G.weighted_euclidean(w, v, dst);
    };
    res = pwsa<Graph, Heap<std::pair<int,int>>, decltype(heuristic)>(G, heuristic, src, dst, split_cutoff, poll_cutoff, exptime, debug);
  };

  auto output = [&] {
    int num_expanded = 0;
    for (int i = 0; i < G.number_vertices(); i++) {
      if (res[i].load() != -1) num_expanded++;
    }
    std::cout << "expanded " << num_expanded << std::endl;
    std::cout << "pathlen " << double(res[dst].load())/10000.0 << std::endl;
  };

  auto destroy = [&] {;};

  pasl::sched::launch(argc, argv, init, run, output, destroy);
  return 0;
}
<commit_msg>fix headers<commit_after>/* COPYRIGHT (c) 2015 Sam Westrick, Laxman Dhulipala, Umut Acar,
 * Arthur Chargueraud, and Michael Rainey.
 * All rights reserved.
 *
 * \file pwsa.cpp
 */
#include "benchmark.hpp"
#include "pwsa.hpp"
#include "bin_heap.hpp"
#include "weighted_graph.hpp"

int main(int argc, char** argv) {
  int split_cutoff; // (K)
  int poll_cutoff; // (D)
  std::string fname;
  int srow;
  int scol;
  int drow;
  int dcol;
  double w;
  double exptime;
  bool debug;

  Graph G;
  int src;
  int dst;

  std::atomic<int>* res;

  auto init = [&] {
    split_cutoff = (int)pasl::util::cmdline::parse_or_default_int("K", 10000);
    poll_cutoff = (int)pasl::util::cmdline::parse_or_default_int("D", 10000);
    fname = pasl::util::cmdline::parse_or_default_string("map", "maps/simple_map.map");
    srow = (int)pasl::util::cmdline::parse_or_default_int("sr", 1);
    scol = (int)pasl::util::cmdline::parse_or_default_int("sc", 1);
    drow = (int)pasl::util::cmdline::parse_or_default_int("dr", 1);
    dcol = (int)pasl::util::cmdline::parse_or_default_int("dc", 1);
    w = (double)pasl::util::cmdline::parse_or_default_float("w", 1.0);
    exptime = (double)pasl::util::cmdline::parse_or_default_float("exptime", 0.0000000001);
    debug = pasl::util::cmdline::parse_or_default_bool("debug", false);

    G = Graph(fname.c_str());

    src = G.vertex_at(srow, scol);
    dst = G.vertex_at(drow, dcol);
  };

  auto run = [&] (bool sequential) {
    auto heuristic = [&] (int v) {
      return G.weighted_euclidean(w, v, dst);
    };
    res = pwsa<Graph, Heap<std::pair<int,int>>, decltype(heuristic)>(G, heuristic, src, dst, split_cutoff, poll_cutoff, exptime, debug);
  };

  auto output = [&] {
    int num_expanded = 0;
    for (int i = 0; i < G.number_vertices(); i++) {
      if (res[i].load() != -1) num_expanded++;
    }
    std::cout << "expanded " << num_expanded << std::endl;
    std::cout << "pathlen " << double(res[dst].load())/10000.0 << std::endl;
  };

  auto destroy = [&] {;};

  pasl::sched::launch(argc, argv, init, run, output, destroy);
  return 0;
}
<|endoftext|>


<commit_before>#include <vector>
#include <fstream>

#include "color/color.hpp"

#include "./model/invoke.hpp"
#include "./model/operation.hpp"
#include "./model/make.hpp"
#include "./model/intrisic_conversion.hpp"
#include "./model/set.hpp"
#include "./model/get.hpp"
#include "./model/conversion.hpp"

void invoke()
 {
  test_invoke< color::category::rgb_uint8   >();
  test_invoke< color::category::rgb_uint16  >();
  test_invoke< color::category::rgb_uint32  >();
  test_invoke< color::category::rgb_uint64  >();
  test_invoke< color::category::rgb_float   >();
  test_invoke< color::category::rgb_double  >();
  test_invoke< color::category::rgb_ldouble >();

  test_operation< color::category::rgb_uint8   >();
  test_operation< color::category::rgb_uint16  >();
  test_operation< color::category::rgb_uint32  >();
  test_operation< color::category::rgb_uint64  >();
  test_operation< color::category::rgb_float   >();
  test_operation< color::category::rgb_double  >();
  test_operation< color::category::rgb_ldouble >();

  test_make< color::category::rgb_uint8   >();
  test_make< color::category::rgb_uint16  >();
  test_make< color::category::rgb_uint32  >();
  test_make< color::category::rgb_uint64  >();
  test_make< color::category::rgb_float   >();
  test_make< color::category::rgb_double  >();
  test_make< color::category::rgb_ldouble >();

  test_conversion< color::rgb, color::rgb >();
  test_conversion< color::rgb, color::cmy >();
  test_conversion< color::rgb, color::gray >();
  test_conversion< color::rgb, color::yiq >();
  test_conversion< color::rgb, color::yuv >();
  test_conversion< color::rgb, color::xyz >();

  test_conversion< color::cmy, color::cmy >();
  test_conversion< color::cmy, color::rgb >();
  test_conversion< color::cmy, color::cmyk >();
  test_conversion< color::cmy, color::gray >();

  test_conversion< color::gray, color::gray >();
  test_conversion< color::gray, color::rgb >();
  test_conversion< color::gray, color::cmy >();
  test_conversion< color::gray, color::hsl >();
  test_conversion< color::gray, color::hsv >();
  test_conversion< color::gray, color::yiq >();
  test_conversion< color::gray, color::yuv >();

  test_conversion< color::yiq, color::yiq >();
  test_conversion< color::yiq, color::rgb >();

  test_conversion< color::yuv, color::yuv >();
  test_conversion< color::yuv, color::rgb >();

  test_conversion< color::xyz, color::xyz >();
  test_conversion< color::xyz, color::rgb >();
 }

template < typename model_name >
void make_image(std::string const& name, float y_plane = 0.5 )
 {
  int height = 1000;
  int width  = 1000;
  typedef unsigned char targa_header_struct[18];

  targa_header_struct header;

  void targa_make_header(int height, int width, targa_header_struct header);

  targa_make_header( height, width, header);

  std::vector< color::rgb<std::uint32_t> >   image(height * width);

  for (int y = 0; y < height; y++)
   {
    for (int x = 0; x < width; x++)
     {
      image[y * width + x].set<3>(255);
      image[y * width + x] = model_name( { y / double(height), y_plane, x / double(width) } );
     }
   }

  std::ofstream of(name, std::ios_base::binary);
  of.write((const char *)header, 18);
  of.write((const char *)image.data(), image.size() * 4);
 }

int main(int argc, char const *argv[])
 {

  make_image<color::rgb<double> >( "image-rgb.tga");
  make_image<color::cmy<double> >( "image-cmy.tga");
  make_image<color::cmyk<double> >("image-cmyk.tga");
  make_image<color::hsl<double> >( "image-hsl.tga");
  make_image<color::hsv<double> >( "image-hsv.tga");
  make_image<color::xyz<double> >( "image-xyz.tga");
  make_image<color::yiq<double> >( "image-yiq.tga");

  make_image<color::yuv<double> >("image-yuv_0.0.tga", 0.0);
  make_image<color::yuv<double> >("image-yuv_0.1.tga", 0.1);
  make_image<color::yuv<double> >("image-yuv_0.2.tga", 0.2);
  make_image<color::yuv<double> >("image-yuv_0.3.tga", 0.3);
  make_image<color::yuv<double> >("image-yuv_0.4.tga", 0.4);
  make_image<color::yuv<double> >("image-yuv_0.5.tga", 0.5);
  make_image<color::yuv<double> >("image-yuv_0.6.tga", 0.6);
  make_image<color::yuv<double> >("image-yuv_0.7.tga", 0.7);
  make_image<color::yuv<double> >("image-yuv_0.8.tga", 0.8);
  make_image<color::yuv<double> >("image-yuv_0.9.tga", 0.9);
  make_image<color::yuv<double> >("image-yuv_1.0.tga", 1.0);

  //invoke();

  extern void check_conversion();
  check_conversion();

  //extern void make_test();
  //make_test();

  return 0;
 }

<commit_msg>* fix: [test] take bounds values<commit_after>#include <vector>
#include <fstream>

#include "color/color.hpp"

#include "./model/invoke.hpp"
#include "./model/operation.hpp"
#include "./model/make.hpp"
#include "./model/intrisic_conversion.hpp"
#include "./model/set.hpp"
#include "./model/get.hpp"
#include "./model/conversion.hpp"

void invoke()
 {
  test_invoke< color::category::rgb_uint8   >();
  test_invoke< color::category::rgb_uint16  >();
  test_invoke< color::category::rgb_uint32  >();
  test_invoke< color::category::rgb_uint64  >();
  test_invoke< color::category::rgb_float   >();
  test_invoke< color::category::rgb_double  >();
  test_invoke< color::category::rgb_ldouble >();

  test_operation< color::category::rgb_uint8   >();
  test_operation< color::category::rgb_uint16  >();
  test_operation< color::category::rgb_uint32  >();
  test_operation< color::category::rgb_uint64  >();
  test_operation< color::category::rgb_float   >();
  test_operation< color::category::rgb_double  >();
  test_operation< color::category::rgb_ldouble >();

  test_make< color::category::rgb_uint8   >();
  test_make< color::category::rgb_uint16  >();
  test_make< color::category::rgb_uint32  >();
  test_make< color::category::rgb_uint64  >();
  test_make< color::category::rgb_float   >();
  test_make< color::category::rgb_double  >();
  test_make< color::category::rgb_ldouble >();

  test_conversion< color::rgb, color::rgb >();
  test_conversion< color::rgb, color::cmy >();
  test_conversion< color::rgb, color::gray >();
  test_conversion< color::rgb, color::yiq >();
  test_conversion< color::rgb, color::yuv >();
  test_conversion< color::rgb, color::xyz >();

  test_conversion< color::cmy, color::cmy >();
  test_conversion< color::cmy, color::rgb >();
  test_conversion< color::cmy, color::cmyk >();
  test_conversion< color::cmy, color::gray >();

  test_conversion< color::gray, color::gray >();
  test_conversion< color::gray, color::rgb >();
  test_conversion< color::gray, color::cmy >();
  test_conversion< color::gray, color::hsl >();
  test_conversion< color::gray, color::hsv >();
  test_conversion< color::gray, color::yiq >();
  test_conversion< color::gray, color::yuv >();

  test_conversion< color::yiq, color::yiq >();
  test_conversion< color::yiq, color::rgb >();

  test_conversion< color::yuv, color::yuv >();
  test_conversion< color::yuv, color::rgb >();

  test_conversion< color::xyz, color::xyz >();
  test_conversion< color::xyz, color::rgb >();
 }

template < typename model_name >
void make_image(std::string const& name, float y_plane = 0.5 )
 {
  int height = 1000;
  int width  = 1000;
  typedef unsigned char targa_header_struct[18];

  typedef ::color::_internal::diverse< typename model_name::category_type, double  > diverse_type;

  targa_header_struct header;

  void targa_make_header(int height, int width, targa_header_struct header);

  targa_make_header( height, width, header);

  std::vector< color::rgb<std::uint32_t> >   image(height * width);

  for (int y = 0; y < height; y++)
   {
    for (int x = 0; x < width; x++)
     {
      image[y * width + x].set<3>(255);
      image[y * width + x] = model_name( { diverse_type::template process<0>( y / double(height) ),
                                           diverse_type::template process<1>( y_plane ),
                                           diverse_type::template process<2>( x / double(width) ) } );
     }
   }

  std::ofstream of(name, std::ios_base::binary);
  of.write((const char *)header, 18);
  of.write((const char *)image.data(), image.size() * 4);
 }

int main(int argc, char const *argv[])
 {

  make_image<color::hsl<double> >( "image-hsl.tga");
  make_image<color::hsv<double> >( "image-hsv.tga");
  make_image<color::rgb<double> >( "image-rgb.tga");
  make_image<color::cmy<double> >( "image-cmy.tga");
  make_image<color::cmyk<double> >("image-cmyk.tga");
  make_image<color::xyz<double> >( "image-xyz.tga");
  make_image<color::yiq<double> >( "image-yiq.tga");

  make_image<color::yuv<double> >("image-yuv_0.0.tga", 0.0);
  make_image<color::yuv<double> >("image-yuv_0.1.tga", 0.1);
  make_image<color::yuv<double> >("image-yuv_0.2.tga", 0.2);
  make_image<color::yuv<double> >("image-yuv_0.3.tga", 0.3);
  make_image<color::yuv<double> >("image-yuv_0.4.tga", 0.4);
  make_image<color::yuv<double> >("image-yuv_0.5.tga", 0.5);
  make_image<color::yuv<double> >("image-yuv_0.6.tga", 0.6);
  make_image<color::yuv<double> >("image-yuv_0.7.tga", 0.7);
  make_image<color::yuv<double> >("image-yuv_0.8.tga", 0.8);
  make_image<color::yuv<double> >("image-yuv_0.9.tga", 0.9);
  make_image<color::yuv<double> >("image-yuv_1.0.tga", 1.0);

  //invoke();

  extern void check_conversion();
  check_conversion();

  //extern void make_test();
  //make_test();

  return 0;
 }

<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>

#include "RaZ/RaZ.hpp"

int main() {
  Raz::WindowPtr window = std::make_unique<Raz::Window>(1280, 720, "RaZ - Full demo", 4);
  window->enableOverlay();

  Raz::VertexShaderPtr vertShader = std::make_unique<Raz::VertexShader>("../../shaders/vert.glsl");
  Raz::FragmentShaderPtr fragShader;

  const auto img = std::make_shared<Raz::Texture>("../../assets/textures/lava.tga");

  const auto startTime = std::chrono::system_clock::now();
  // If FBX SDK linked, load an FBX mesh
#if defined(FBX_ENABLED)
  fragShader = std::make_unique<Raz::FragmentShader>("../../shaders/blinn-phong.glsl");
  Raz::ModelPtr model = Raz::Model::import("../../assets/meshes/shaderBall.fbx");

  dynamic_cast<Raz::MaterialStandard*>(model->getMesh()->getMaterials().front().get())->setDiffuseMap(img);

  model->translate(0.f, -1.f, 0.f);
  model->scale(0.01f);
  model->rotate(180.f, 0.f, 1.f, 0.f);
#else
  fragShader = std::make_unique<Raz::FragmentShader>("../../shaders/cook-torrance.glsl");
  Raz::ModelPtr model = Raz::Model::import("../../assets/meshes/shield.obj");

  dynamic_cast<Raz::MaterialCookTorrance*>(model->getMesh()->getMaterials().front().get())->setAlbedoMap(img);

  model->scale(0.2f);
  model->rotate(180.f, 0.f, 1.f, 0.f);
#endif
  const auto endTime = std::chrono::system_clock::now();

  std::cout << "Mesh loading duration: "
            << std::chrono::duration_cast<std::chrono::duration<float>>(endTime - startTime).count()
            << " seconds." << std::endl;

  Raz::ScenePtr scene = std::make_unique<Raz::Scene>(std::move(vertShader), std::move(fragShader));

  Raz::CubemapPtr cubemap = std::make_unique<Raz::Cubemap>("../../assets/skyboxes/clouds_right.png",
                                                           "../../assets/skyboxes/clouds_left.png",
                                                           "../../assets/skyboxes/clouds_top.png",
                                                           "../../assets/skyboxes/clouds_bottom.png",
                                                           "../../assets/skyboxes/clouds_front.png",
                                                           "../../assets/skyboxes/clouds_back.png");

  /*Raz::LightPtr light = std::make_unique<Raz::PointLight>(Raz::Vec3f({ 0.f, 1.f, 0.f }),  // Position
                                                          10.f,                           // Energy
                                                          Raz::Vec3f({ 1.f, 1.f, 1.f })); // Color (R/G/B)*/
  Raz::LightPtr light = std::make_unique<Raz::DirectionalLight>(Raz::Vec3f({ 0.f, 0.f, 1.f }),  // Direction
                                                                1.f,                            // Energy
                                                                Raz::Vec3f({ 1.f, 1.f, 1.f }),  // Color (R/G/B)
                                                                Raz::Vec3f({ 0.f, 1.f, 0.f })); // Position

  Raz::CameraPtr camera = std::make_unique<Raz::Camera>(window->getWidth(),
                                                        window->getHeight(),
                                                        45.f,                            // Field of view
                                                        0.1f, 100.f,                     // Near plane, far plane
                                                        Raz::Vec3f({ 0.f, 0.f, -5.f })); // Initial position

  const auto modelPtr  = model.get();
  const auto lightPtr  = light.get();
  const auto cameraPtr = camera.get();

  scene->setCubemap(std::move(cubemap));
  scene->addModel(std::move(model));
  scene->addLight(std::move(light));
  scene->updateLights();
  scene->load();

  Raz::Application app(std::move(window), std::move(scene), std::move(camera));

  auto& windowPtr = app.getWindow();
  auto& scenePtr  = app.getScene();

  // Allow wireframe toggling
  bool isWireframe = false;
  windowPtr->addKeyCallback(Raz::Keyboard::Z, [&isWireframe] () {
    isWireframe = !isWireframe;
    glPolygonMode(GL_FRONT_AND_BACK, (isWireframe ? GL_LINE : GL_FILL));
  });

  // Allow face culling toggling
  bool hasFaceCulling = true;
  windowPtr->addKeyCallback(Raz::Keyboard::N, [&hasFaceCulling, &windowPtr] () {
    windowPtr->enableFaceCulling((hasFaceCulling = !hasFaceCulling));
  });

  windowPtr->addKeyCallback(Raz::Keyboard::ESCAPE, [&app] () { app.quit(); });

  // Camera controls
  windowPtr->addKeyCallback(Raz::Keyboard::SPACE, [&cameraPtr] () { cameraPtr->move( 0.f,  0.5f, 0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::V,     [&cameraPtr] () { cameraPtr->move( 0.f, -0.5f, 0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::W,     [&cameraPtr] () { cameraPtr->move( 0.f,  0.f,  0.5f); });
  windowPtr->addKeyCallback(Raz::Keyboard::S,     [&cameraPtr] () { cameraPtr->move( 0.f,  0.f, -0.5f); });
  windowPtr->addKeyCallback(Raz::Keyboard::A,     [&cameraPtr] () { cameraPtr->move(-0.5f, 0.f,  0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::D,     [&cameraPtr] () { cameraPtr->move( 0.5f, 0.f,  0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::NUM8,  [&cameraPtr] () { cameraPtr->rotate(-10.f, 1.f, 0.f, 0.f); }); // Looking up
  windowPtr->addKeyCallback(Raz::Keyboard::NUM2,  [&cameraPtr] () { cameraPtr->rotate( 10.f, 1.f, 0.f, 0.f); }); // Looking down
  windowPtr->addKeyCallback(Raz::Keyboard::NUM4,  [&cameraPtr] () { cameraPtr->rotate(-10.f, 0.f, 1.f, 0.f); }); // Looking left
  windowPtr->addKeyCallback(Raz::Keyboard::NUM6,  [&cameraPtr] () { cameraPtr->rotate( 10.f, 0.f, 1.f, 0.f); }); // Looking right

  // Mesh controls
  windowPtr->addKeyCallback(Raz::Keyboard::T,     [&modelPtr] () { modelPtr->move( 0.f,  0.f,  0.5f); });
  windowPtr->addKeyCallback(Raz::Keyboard::G,     [&modelPtr] () { modelPtr->move( 0.f,  0.f, -0.5f); });
  windowPtr->addKeyCallback(Raz::Keyboard::F,     [&modelPtr] () { modelPtr->move(-0.5f, 0.f,  0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::H,     [&modelPtr] () { modelPtr->move( 0.5f, 0.f,  0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::X,     [&modelPtr] () { modelPtr->scale(0.5f); });
  windowPtr->addKeyCallback(Raz::Keyboard::C,     [&modelPtr] () { modelPtr->scale(2.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::UP,    [&modelPtr] () { modelPtr->rotate(-10.f, 1.f, 0.f, 0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::DOWN,  [&modelPtr] () { modelPtr->rotate( 10.f, 1.f, 0.f, 0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::LEFT,  [&modelPtr] () { modelPtr->rotate(-10.f, 0.f, 1.f, 0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::RIGHT, [&modelPtr] () { modelPtr->rotate( 10.f, 0.f, 1.f, 0.f); });

  // Light controls
  windowPtr->addKeyCallback(Raz::Keyboard::I, [&lightPtr, &scenePtr] () {
    lightPtr->translate(0.f, 0.f, 0.5f);
    scenePtr->updateLights();
  });
  windowPtr->addKeyCallback(Raz::Keyboard::K, [&lightPtr, &scenePtr] () {
    lightPtr->translate(0.f, 0.f, -0.5f);
    scenePtr->updateLights();
  });
  windowPtr->addKeyCallback(Raz::Keyboard::J, [&lightPtr, &scenePtr] () {
    lightPtr->translate(-0.5f, 0.f, 0.f);
    scenePtr->updateLights();
  });
  windowPtr->addKeyCallback(Raz::Keyboard::L, [&lightPtr, &scenePtr] () {
    lightPtr->translate(0.5f, 0.f, 0.f);
    scenePtr->updateLights();
  });

  windowPtr->addKeyCallback(Raz::Keyboard::NUM0, [&scenePtr, &cameraPtr] () {
    scenePtr->addLight(std::make_unique<Raz::PointLight>(cameraPtr->getPosition(), 10.f, Raz::Vec3f({ 1.f, 1.f, 1.f })));
    scenePtr->updateLights();
  });

  windowPtr->addKeyCallback(Raz::Keyboard::F5, [&app] () { app.updateShaders(); });

  // Mouse callbacks
  windowPtr->addMouseScrollCallback([&cameraPtr] (double /* xOffset */, double yOffset) {
    cameraPtr->setFieldOfView(std::max(1.f, std::min(90.f, cameraPtr->getFieldOfViewDegrees() + static_cast<float>(-yOffset) * 2.f)));
  });
  windowPtr->addMouseMoveCallback([&cameraPtr, &windowPtr] (double xMove, double yMove) {
    cameraPtr->rotate(1.f,
                      (static_cast<float>(yMove) / windowPtr->getHeight() * 90.f), // X & Y moves are inverted, unsure of why for now
                      (static_cast<float>(xMove) / windowPtr->getWidth() * 90.f),  // Dividing by window size to scale X & Y between -1 and 1
                      0.f);
  });
  windowPtr->disableCursor();

  // Overlay features
  windowPtr->addOverlayText("RaZ - Full demo");
  windowPtr->addOverlayText("Scene's informations:");
  windowPtr->addOverlayText(std::to_string(scenePtr->recoverVertexCount()) + " vertices, "
                          + std::to_string(scenePtr->recoverTriangleCount()) + " triangles");
  windowPtr->addOverlayCheckbox("Enable face culling",
                                true,
                                [&windowPtr] () { windowPtr->enableFaceCulling(); },
                                [&windowPtr] () { windowPtr->disableFaceCulling(); });
  windowPtr->addOverlayCheckbox("Enable vertical sync",
                                windowPtr->recoverVerticalSyncState(),
                                [&windowPtr] () { windowPtr->enableVerticalSync(); },
                                [&windowPtr] () { windowPtr->disableVerticalSync(); });
  windowPtr->addOverlayFrameTime("Frame time: %.3f ms/frame"); // Frame time's & FPS counter's texts must be formatted
  windowPtr->addOverlayFpsCounter("FPS: %.1f");

  auto lastTime = std::chrono::system_clock::now();
  uint16_t nbFrames = 0;

  while (app.run()) {
    const auto currentTime = std::chrono::system_clock::now();
    ++nbFrames;

    if (std::chrono::duration_cast<std::chrono::duration<float>>(currentTime - lastTime).count() >= 1.f) {
      app.getWindow()->setTitle("RaZ - " + std::to_string(nbFrames) + " FPS");

      nbFrames = 0;
      lastTime = currentTime;
    }
  }

  return EXIT_SUCCESS;
}
<commit_msg>[Update] Delta time is now handled by move callbacks in full demo [Update] Added camera speed in full demo, 2x faster with left shift [Update] Adding a light in full demo is now with left click (prev. NUM0)<commit_after>#include <chrono>
#include <iostream>

#include "RaZ/RaZ.hpp"

int main() {
  Raz::WindowPtr window = std::make_unique<Raz::Window>(1280, 720, "RaZ - Full demo", 4);
  window->enableOverlay();

  Raz::VertexShaderPtr vertShader = std::make_unique<Raz::VertexShader>("../../shaders/vert.glsl");
  Raz::FragmentShaderPtr fragShader;

  const auto img = std::make_shared<Raz::Texture>("../../assets/textures/lava.tga");

  const auto startTime = std::chrono::system_clock::now();
  // If FBX SDK linked, load an FBX mesh
#if defined(FBX_ENABLED)
  fragShader = std::make_unique<Raz::FragmentShader>("../../shaders/blinn-phong.glsl");
  Raz::ModelPtr model = Raz::Model::import("../../assets/meshes/shaderBall.fbx");

  dynamic_cast<Raz::MaterialStandard*>(model->getMesh()->getMaterials().front().get())->setDiffuseMap(img);

  model->translate(0.f, -1.f, 0.f);
  model->scale(0.01f);
  model->rotate(180.f, 0.f, 1.f, 0.f);
#else
  fragShader = std::make_unique<Raz::FragmentShader>("../../shaders/cook-torrance.glsl");
  Raz::ModelPtr model = Raz::Model::import("../../assets/meshes/shield.obj");

  dynamic_cast<Raz::MaterialCookTorrance*>(model->getMesh()->getMaterials().front().get())->setAlbedoMap(img);

  model->scale(0.2f);
  model->rotate(180.f, 0.f, 1.f, 0.f);
#endif
  const auto endTime = std::chrono::system_clock::now();

  std::cout << "Mesh loading duration: "
            << std::chrono::duration_cast<std::chrono::duration<float>>(endTime - startTime).count()
            << " seconds." << std::endl;

  Raz::ScenePtr scene = std::make_unique<Raz::Scene>(std::move(vertShader), std::move(fragShader));

  Raz::CubemapPtr cubemap = std::make_unique<Raz::Cubemap>("../../assets/skyboxes/clouds_right.png",
                                                           "../../assets/skyboxes/clouds_left.png",
                                                           "../../assets/skyboxes/clouds_top.png",
                                                           "../../assets/skyboxes/clouds_bottom.png",
                                                           "../../assets/skyboxes/clouds_front.png",
                                                           "../../assets/skyboxes/clouds_back.png");

  /*Raz::LightPtr light = std::make_unique<Raz::PointLight>(Raz::Vec3f({ 0.f, 1.f, 0.f }),  // Position
                                                          10.f,                           // Energy
                                                          Raz::Vec3f({ 1.f, 1.f, 1.f })); // Color (R/G/B)*/
  Raz::LightPtr light = std::make_unique<Raz::DirectionalLight>(Raz::Vec3f({ 0.f, 0.f, 1.f }),  // Direction
                                                                1.f,                            // Energy
                                                                Raz::Vec3f({ 1.f, 1.f, 1.f }),  // Color (R/G/B)
                                                                Raz::Vec3f({ 0.f, 1.f, 0.f })); // Position

  Raz::CameraPtr camera = std::make_unique<Raz::Camera>(window->getWidth(),
                                                        window->getHeight(),
                                                        45.f,                            // Field of view
                                                        0.1f, 100.f,                     // Near plane, far plane
                                                        Raz::Vec3f({ 0.f, 0.f, -5.f })); // Initial position

  const auto modelPtr  = model.get();
  const auto lightPtr  = light.get();
  const auto cameraPtr = camera.get();

  scene->setCubemap(std::move(cubemap));
  scene->addModel(std::move(model));
  scene->addLight(std::move(light));
  scene->updateLights();
  scene->load();

  Raz::Application app(std::move(window), std::move(scene), std::move(camera));

  auto& windowPtr = app.getWindow();
  auto& scenePtr  = app.getScene();

  // Allow wireframe toggling
  bool isWireframe = false;
  windowPtr->addKeyCallback(Raz::Keyboard::Z, [&isWireframe] (float /* deltaTime */) {
    isWireframe = !isWireframe;
    glPolygonMode(GL_FRONT_AND_BACK, (isWireframe ? GL_LINE : GL_FILL));
  });

  // Allow face culling toggling
  bool hasFaceCulling = true;
  windowPtr->addKeyCallback(Raz::Keyboard::N, [&hasFaceCulling, &windowPtr] (float /* deltaTime */) {
    windowPtr->enableFaceCulling((hasFaceCulling = !hasFaceCulling));
  });

  windowPtr->addKeyCallback(Raz::Keyboard::ESCAPE, [&app] (float /* deltaTime */) { app.quit(); });

  // Camera controls
  float cameraSpeed = 1.f;
  windowPtr->addKeyCallback(Raz::Keyboard::LEFT_SHIFT,
                            [&cameraSpeed] (float /* deltaTime */) { cameraSpeed = 2.f; },
                            [&cameraSpeed] () { cameraSpeed = 1.f; });
  windowPtr->addKeyCallback(Raz::Keyboard::SPACE, [&cameraPtr, &cameraSpeed] (float deltaTime) {
    cameraPtr->move(0.f, (10.f * deltaTime) * cameraSpeed, 0.f);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::V, [&cameraPtr, &cameraSpeed] (float deltaTime) {
    cameraPtr->move(0.f, (-10.f * deltaTime) * cameraSpeed, 0.f);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::W, [&cameraPtr, &cameraSpeed] (float deltaTime) {
    cameraPtr->move(0.f, 0.f, (10.f * deltaTime) * cameraSpeed);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::S, [&cameraPtr, &cameraSpeed] (float deltaTime) {
    cameraPtr->move(0.f,  0.f, (-10.f * deltaTime) * cameraSpeed);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::A, [&cameraPtr, &cameraSpeed] (float deltaTime) {
    cameraPtr->move((-10.f * deltaTime) * cameraSpeed, 0.f, 0.f);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::D, [&cameraPtr, &cameraSpeed] (float deltaTime) {
    cameraPtr->move((10.f * deltaTime) * cameraSpeed, 0.f, 0.f);
  });

  windowPtr->addKeyCallback(Raz::Keyboard::NUM8, [&cameraPtr] (float deltaTime) {
    cameraPtr->rotate(-1.f, 90.f * deltaTime, 0.f, 0.f); // Looking up
  });
  windowPtr->addKeyCallback(Raz::Keyboard::NUM2, [&cameraPtr] (float deltaTime) {
    cameraPtr->rotate(1.f, 90.f * deltaTime, 0.f, 0.f); // Looking down
  });
  windowPtr->addKeyCallback(Raz::Keyboard::NUM4, [&cameraPtr] (float deltaTime) {
    cameraPtr->rotate(-1.f, 0.f, 90.f * deltaTime, 0.f); // Looking left
  });
  windowPtr->addKeyCallback(Raz::Keyboard::NUM6, [&cameraPtr] (float deltaTime) {
    cameraPtr->rotate(1.f, 0.f, 90.f * deltaTime, 0.f); // Looking right
  });

  // Mesh controls
  windowPtr->addKeyCallback(Raz::Keyboard::T, [&modelPtr] (float deltaTime) { modelPtr->move(0.f, 0.f,  10.f * deltaTime); });
  windowPtr->addKeyCallback(Raz::Keyboard::G, [&modelPtr] (float deltaTime) { modelPtr->move(0.f, 0.f, -10.f * deltaTime); });
  windowPtr->addKeyCallback(Raz::Keyboard::F, [&modelPtr] (float deltaTime) { modelPtr->move(-10.f * deltaTime, 0.f, 0.f); });
  windowPtr->addKeyCallback(Raz::Keyboard::H, [&modelPtr] (float deltaTime) { modelPtr->move( 10.f * deltaTime, 0.f, 0.f); });

  windowPtr->addKeyCallback(Raz::Keyboard::UP, [&modelPtr] (float deltaTime) {
    modelPtr->rotate(-1.f, 90.f * deltaTime, 0.f, 0.f);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::DOWN, [&modelPtr] (float deltaTime) {
    modelPtr->rotate( 1.f, 90.f * deltaTime, 0.f, 0.f);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::LEFT, [&modelPtr] (float deltaTime) {
    modelPtr->rotate(-1.f, 0.f, 90.f * deltaTime, 0.f);
  });
  windowPtr->addKeyCallback(Raz::Keyboard::RIGHT, [&modelPtr] (float deltaTime) {
    modelPtr->rotate( 1.f, 0.f, 90.f * deltaTime, 0.f);
  });

  // Light controls
  windowPtr->addKeyCallback(Raz::Keyboard::I, [&lightPtr, &scenePtr] (float deltaTime) {
    lightPtr->translate(0.f, 0.f, 10.f * deltaTime);
    scenePtr->updateLights();
  });
  windowPtr->addKeyCallback(Raz::Keyboard::K, [&lightPtr, &scenePtr] (float deltaTime) {
    lightPtr->translate(0.f, 0.f, -10.f * deltaTime);
    scenePtr->updateLights();
  });
  windowPtr->addKeyCallback(Raz::Keyboard::J, [&lightPtr, &scenePtr] (float deltaTime) {
    lightPtr->translate(-10.f * deltaTime, 0.f, 0.f);
    scenePtr->updateLights();
  });
  windowPtr->addKeyCallback(Raz::Keyboard::L, [&lightPtr, &scenePtr] (float deltaTime) {
    lightPtr->translate(10.f * deltaTime, 0.f, 0.f);
    scenePtr->updateLights();
  });

  windowPtr->addMouseButtonCallback(Raz::Mouse::LEFT_CLICK, [&scenePtr, &cameraPtr] (float /* deltaTime */) {
    scenePtr->addLight(std::make_unique<Raz::PointLight>(cameraPtr->getPosition(), 10.f, Raz::Vec3f({ 1.f, 1.f, 1.f })));
    scenePtr->updateLights();
  });

  windowPtr->addKeyCallback(Raz::Keyboard::F5, [&app] (float /* deltaTime */) { app.updateShaders(); });

  // Mouse callbacks
  windowPtr->addMouseScrollCallback([&cameraPtr] (double /* xOffset */, double yOffset) {
    cameraPtr->setFieldOfView(std::max(1.f, std::min(90.f, cameraPtr->getFieldOfViewDegrees() + static_cast<float>(-yOffset) * 2.f)));
  });

  windowPtr->disableCursor(); // Disabling mouse cursor to allow continous rotations
  windowPtr->addMouseMoveCallback([&cameraPtr, &windowPtr] (double xMove, double yMove) {
    cameraPtr->rotate(1.f,
                      (static_cast<float>(yMove) / windowPtr->getHeight() * 90.f), // X & Y moves are inverted, unsure of why for now
                      (static_cast<float>(xMove) / windowPtr->getWidth() * 90.f),  // Dividing by window size to scale between -1 and 1
                      0.f);
  });

  // Overlay features
  windowPtr->addOverlayText("RaZ - Full demo");
  windowPtr->addOverlayText("Scene's informations:");
  windowPtr->addOverlayText(std::to_string(scenePtr->recoverVertexCount()) + " vertices, "
                          + std::to_string(scenePtr->recoverTriangleCount()) + " triangles");
  windowPtr->addOverlayCheckbox("Enable face culling",
                                true,
                                [&windowPtr] () { windowPtr->enableFaceCulling(); },
                                [&windowPtr] () { windowPtr->disableFaceCulling(); });
  windowPtr->addOverlayCheckbox("Enable vertical sync",
                                windowPtr->recoverVerticalSyncState(),
                                [&windowPtr] () { windowPtr->enableVerticalSync(); },
                                [&windowPtr] () { windowPtr->disableVerticalSync(); });
  windowPtr->addOverlayFrameTime("Frame time: %.3f ms/frame"); // Frame time's & FPS counter's texts must be formatted
  windowPtr->addOverlayFpsCounter("FPS: %.1f");

  auto lastTime = std::chrono::system_clock::now();
  uint16_t nbFrames = 0;

  while (app.run()) {
    const auto currentTime = std::chrono::system_clock::now();
    ++nbFrames;

    if (std::chrono::duration_cast<std::chrono::duration<float>>(currentTime - lastTime).count() >= 1.f) {
      app.getWindow()->setTitle("RaZ - " + std::to_string(nbFrames) + " FPS");

      nbFrames = 0;
      lastTime = currentTime;
    }
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <gtest/gtest.h>
#include <arrayfire.h>
#include <af/dim4.hpp>
#include <af/defines.h>
#include <af/traits.hpp>
#include <vector>
#include <iostream>
#include <complex>
#include <string>
#include <testHelpers.hpp>
#include <algorithm>

using std::vector;
using std::string;
using std::cout;
using std::endl;
using af::cfloat;
using af::cdouble;

template<typename T>
class Wrap : public ::testing::Test
{
    public:
        virtual void SetUp() {
        }
};

// create a list of types to be tested
typedef ::testing::Types<float, double, cfloat, cdouble, int, unsigned int, intl, uintl, char, unsigned char> TestTypes;

// register the type list
TYPED_TEST_CASE(Wrap, TestTypes);

template<typename T>
double get_val(T val)
{
    return val;
}

template<> double get_val<cfloat>(cfloat val)
{
    return abs(val);
}

template<> double get_val<cdouble>(cdouble val)
{
    return abs(val);
}

template<> double get_val<unsigned char>(unsigned char val)
{
    return ((int)(val)) % 256;
}

template<> double get_val<char>(char val)
{
    return (val != 0);
}

template<typename T>
void wrapTest(const dim_t ix, const dim_t iy,
              const dim_t wx, const dim_t wy,
              const dim_t sx, const dim_t sy,
              const dim_t px, const dim_t py,
              bool cond)
{
    if (noDoubleTests<T>()) return;

    const int nc = 1;

    int lim = std::max((dim_t)2, (dim_t)(250) / (wx * wy));

    af::dtype ty = (af::dtype)af::dtype_traits<T>::af_type;
    af::array in = af::round(lim * af::randu(ix, iy, nc, f32)).as(ty);

    std::vector<T> h_in(in.elements());
    in.host(&h_in[0]);

    std::vector<int> h_factor(ix * iy);

    dim_t ny = (iy + 2 * py - wy) / sy + 1;
    dim_t nx = (ix + 2 * px - wx) / sx + 1;

    for (int idy = 0; idy < ny; idy++) {
        int fy = idy * sy - py;
        if (fy + wy < 0 || fy >= iy) continue;

        for (int idx = 0; idx < nx; idx++) {
            int fx = idx * sx - px;
            if (fx + wx < 0 || fx >= ix) continue;

            for (int ly = 0; ly < wy; ly++) {
                if (fy + ly < 0 || fy + ly >= iy) continue;

                for (int lx = 0; lx < wx; lx++) {
                    if (fx + lx < 0 || fx + lx >= ix) continue;
                    h_factor[(fy + ly) * ix + (fx + lx)]++;
                }
            }
        }
    }

    af::array factor(ix, iy, &h_factor[0]);

    af::array in_dim = af::unwrap(in, wx, wy, sx, sy, px, py, cond);
    af::array res_dim = af::wrap(in_dim, ix, iy, wx, wy, sx, sy, px, py, cond);

    ASSERT_EQ(in.elements(), res_dim.elements());

    std::vector<T> h_res(ix * iy);
    res_dim.host(&h_res[0]);

    for (int n = 0; n < nc; n++) {
        T *iptr = &h_in[n * ix * iy];
        T *rptr = &h_res[n * ix * iy];

        for (int y = 0; y < iy; y++) {
            for (int x = 0; x < ix; x++) {

                // FIXME: Use a better test
                T ival = iptr[y * ix + x];
                T rval = rptr[y * ix + x];
                int factor = h_factor[y * ix + x];

                if (abs(ival) == 0) continue;

                ASSERT_NEAR(get_val<T>(ival * factor), get_val<T>(rval), 1E-5)
                    << "at " << x << "," << y <<  " for cond  == " << cond << std::endl;
            }
        }

    }
}

#define WRAP_INIT(desc, ix, iy, wx, wy, sx, sy, px,py)              \
    TYPED_TEST(Wrap, Col##desc)                                     \
    {                                                               \
        wrapTest<TypeParam>(ix, iy, wx, wy, sx, sy, px, py, true ); \
    }                                                               \
    TYPED_TEST(Wrap, Row##desc)                                     \
    {                                                               \
        wrapTest<TypeParam>(ix, iy, wx, wy, sx, sy, px, py, false); \
    }

    WRAP_INIT(00, 300, 100,  3,  3,  1,  1,  0,  0);
    WRAP_INIT(01, 300, 100,  3,  3,  1,  1,  1,  1);
    WRAP_INIT(03, 300, 100,  3,  3,  2,  2,  0,  0);
    WRAP_INIT(04, 300, 100,  3,  3,  2,  2,  1,  1);
    WRAP_INIT(05, 300, 100,  3,  3,  2,  2,  2,  2);
    WRAP_INIT(06, 300, 100,  3,  3,  3,  3,  0,  0);
    WRAP_INIT(07, 300, 100,  3,  3,  3,  3,  1,  1);
    WRAP_INIT(08, 300, 100,  3,  3,  3,  3,  2,  2);
    WRAP_INIT(09, 300, 100,  4,  4,  1,  1,  0,  0);
    WRAP_INIT(13, 300, 100,  4,  4,  2,  2,  0,  0);
    WRAP_INIT(14, 300, 100,  4,  4,  2,  2,  1,  1);
    WRAP_INIT(15, 300, 100,  4,  4,  2,  2,  2,  2);
    WRAP_INIT(16, 300, 100,  4,  4,  2,  2,  3,  3);
    WRAP_INIT(17, 300, 100,  4,  4,  4,  4,  0,  0);
    WRAP_INIT(18, 300, 100,  4,  4,  4,  4,  1,  1);
    WRAP_INIT(19, 300, 100,  4,  4,  4,  4,  2,  2);
    WRAP_INIT(27, 300, 100,  8,  8,  8,  8,  0,  0);
    WRAP_INIT(28, 300, 100,  8,  8,  8,  8,  7,  7);
    WRAP_INIT(31, 300, 100, 12, 12, 12, 12,  0,  0);
    WRAP_INIT(32, 300, 100, 12, 12, 12, 12,  2,  2);
    WRAP_INIT(35, 300, 100, 16, 16, 16, 16, 15, 15);
    WRAP_INIT(36, 300, 100, 31, 31,  8,  8, 15, 15);
    WRAP_INIT(39, 300, 100,  8, 12,  8, 12,  0,  0);
    WRAP_INIT(40, 300, 100,  8, 12,  8, 12,  7, 11);
    WRAP_INIT(43, 300, 100, 15, 10, 15, 10,  0,  0);
    WRAP_INIT(44, 300, 100, 15, 10, 15, 10, 14,  9);
<commit_msg>Fixing the compile error on windows<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <gtest/gtest.h>
#include <arrayfire.h>
#include <af/dim4.hpp>
#include <af/defines.h>
#include <af/traits.hpp>
#include <vector>
#include <iostream>
#include <complex>
#include <string>
#include <testHelpers.hpp>
#include <algorithm>

using std::vector;
using std::string;
using std::cout;
using std::endl;
using af::cfloat;
using af::cdouble;

template<typename T>
class Wrap : public ::testing::Test
{
    public:
        virtual void SetUp() {
        }
};

// create a list of types to be tested
typedef ::testing::Types<float, double, cfloat, cdouble, int, unsigned int, intl, uintl, char, unsigned char> TestTypes;

// register the type list
TYPED_TEST_CASE(Wrap, TestTypes);

template<typename T>
double get_val(T val)
{
    return val;
}

template<> double get_val<cfloat>(cfloat val)
{
    return abs(val);
}

template<> double get_val<cdouble>(cdouble val)
{
    return abs(val);
}

template<> double get_val<unsigned char>(unsigned char val)
{
    return ((int)(val)) % 256;
}

template<> double get_val<char>(char val)
{
    return (val != 0);
}

template<typename T>
void wrapTest(const dim_t ix, const dim_t iy,
              const dim_t wx, const dim_t wy,
              const dim_t sx, const dim_t sy,
              const dim_t px, const dim_t py,
              bool cond)
{
    if (noDoubleTests<T>()) return;

    const int nc = 1;

    int lim = std::max((dim_t)2, (dim_t)(250) / (wx * wy));

    af::dtype ty = (af::dtype)af::dtype_traits<T>::af_type;
    af::array in = af::round(lim * af::randu(ix, iy, nc, f32)).as(ty);

    std::vector<T> h_in(in.elements());
    in.host(&h_in[0]);

    std::vector<int> h_factor(ix * iy);

    dim_t ny = (iy + 2 * py - wy) / sy + 1;
    dim_t nx = (ix + 2 * px - wx) / sx + 1;

    for (int idy = 0; idy < ny; idy++) {
        int fy = idy * sy - py;
        if (fy + wy < 0 || fy >= iy) continue;

        for (int idx = 0; idx < nx; idx++) {
            int fx = idx * sx - px;
            if (fx + wx < 0 || fx >= ix) continue;

            for (int ly = 0; ly < wy; ly++) {
                if (fy + ly < 0 || fy + ly >= iy) continue;

                for (int lx = 0; lx < wx; lx++) {
                    if (fx + lx < 0 || fx + lx >= ix) continue;
                    h_factor[(fy + ly) * ix + (fx + lx)]++;
                }
            }
        }
    }

    af::array factor(ix, iy, &h_factor[0]);

    af::array in_dim = af::unwrap(in, wx, wy, sx, sy, px, py, cond);
    af::array res_dim = af::wrap(in_dim, ix, iy, wx, wy, sx, sy, px, py, cond);

    ASSERT_EQ(in.elements(), res_dim.elements());

    std::vector<T> h_res(ix * iy);
    res_dim.host(&h_res[0]);

    for (int n = 0; n < nc; n++) {
        T *iptr = &h_in[n * ix * iy];
        T *rptr = &h_res[n * ix * iy];

        for (int y = 0; y < iy; y++) {
            for (int x = 0; x < ix; x++) {

                // FIXME: Use a better test
                T ival = iptr[y * ix + x];
                T rval = rptr[y * ix + x];
                int factor = h_factor[y * ix + x];

                if (get_val(ival) == 0) continue;

                ASSERT_NEAR(get_val<T>(ival * factor), get_val<T>(rval), 1E-5)
                    << "at " << x << "," << y <<  " for cond  == " << cond << std::endl;
            }
        }

    }
}

#define WRAP_INIT(desc, ix, iy, wx, wy, sx, sy, px,py)              \
    TYPED_TEST(Wrap, Col##desc)                                     \
    {                                                               \
        wrapTest<TypeParam>(ix, iy, wx, wy, sx, sy, px, py, true ); \
    }                                                               \
    TYPED_TEST(Wrap, Row##desc)                                     \
    {                                                               \
        wrapTest<TypeParam>(ix, iy, wx, wy, sx, sy, px, py, false); \
    }

    WRAP_INIT(00, 300, 100,  3,  3,  1,  1,  0,  0);
    WRAP_INIT(01, 300, 100,  3,  3,  1,  1,  1,  1);
    WRAP_INIT(03, 300, 100,  3,  3,  2,  2,  0,  0);
    WRAP_INIT(04, 300, 100,  3,  3,  2,  2,  1,  1);
    WRAP_INIT(05, 300, 100,  3,  3,  2,  2,  2,  2);
    WRAP_INIT(06, 300, 100,  3,  3,  3,  3,  0,  0);
    WRAP_INIT(07, 300, 100,  3,  3,  3,  3,  1,  1);
    WRAP_INIT(08, 300, 100,  3,  3,  3,  3,  2,  2);
    WRAP_INIT(09, 300, 100,  4,  4,  1,  1,  0,  0);
    WRAP_INIT(13, 300, 100,  4,  4,  2,  2,  0,  0);
    WRAP_INIT(14, 300, 100,  4,  4,  2,  2,  1,  1);
    WRAP_INIT(15, 300, 100,  4,  4,  2,  2,  2,  2);
    WRAP_INIT(16, 300, 100,  4,  4,  2,  2,  3,  3);
    WRAP_INIT(17, 300, 100,  4,  4,  4,  4,  0,  0);
    WRAP_INIT(18, 300, 100,  4,  4,  4,  4,  1,  1);
    WRAP_INIT(19, 300, 100,  4,  4,  4,  4,  2,  2);
    WRAP_INIT(27, 300, 100,  8,  8,  8,  8,  0,  0);
    WRAP_INIT(28, 300, 100,  8,  8,  8,  8,  7,  7);
    WRAP_INIT(31, 300, 100, 12, 12, 12, 12,  0,  0);
    WRAP_INIT(32, 300, 100, 12, 12, 12, 12,  2,  2);
    WRAP_INIT(35, 300, 100, 16, 16, 16, 16, 15, 15);
    WRAP_INIT(36, 300, 100, 31, 31,  8,  8, 15, 15);
    WRAP_INIT(39, 300, 100,  8, 12,  8, 12,  0,  0);
    WRAP_INIT(40, 300, 100,  8, 12,  8, 12,  7, 11);
    WRAP_INIT(43, 300, 100, 15, 10, 15, 10,  0,  0);
    WRAP_INIT(44, 300, 100, 15, 10, 15, 10, 14,  9);
<|endoftext|>