<commit_before>/***********************************************************************
 util.cpp - Utility functions required by several of the example
 	programs.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2006 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "util.h"

#include <iostream>
#include <iomanip>

// This include isn't needed by util module.  It's just a test of the
// new SSQLS feature allowing the structure to be defined in many
// modules without having a multiply-defined static variable error.
// Don't do this for VC++ 2003: it doesn't support variadic macros,
// which this feature depends on.
#if !defined(_MSC_VER) || _MSC_VER >= 1400
#	define MYSQLPP_SSQLS_NO_STATICS
#	include "stock.h"
#endif

using namespace std;

const char* kpcSampleDatabase = "mysql_cpp_data";

//// print_stock_header ////////////////////////////////////////////////
// Display a header suitable for use with print_stock_rows().

void
print_stock_header(int rows)
{
	cout << "Records found: " << rows << endl << endl;
	cout.setf(ios::left);
	cout << setw(21) << "Item" <<
			setw(10) << "Num" <<
			setw(10) << "Weight" <<
			setw(10) << "Price" <<
			"Date" << endl << endl;
}

//// print_stock_row ///////////////////////////////////////////////////
// Print out a row of data from the stock table, in a format compatible
// with the header printed out in the previous function.

void
print_stock_row(const mysqlpp::sql_char& item, mysqlpp::sql_bigint num,
		mysqlpp::sql_double weight, mysqlpp::sql_double price,
		const mysqlpp::sql_date& date)
{
	char buf[100];
	cout << setw(20) << item << ' ' <<
			setw(9) << num << ' ' <<
			setw(9) << weight << ' ' <<
			setw(9) << price << ' ' <<
			date << endl;
}

//// print_stock_row ///////////////////////////////////////////////////
// Take a Row from the example 'stock' table, break it up into fields,
// and call the above version of this function.

void
print_stock_row(const mysqlpp::Row& row)
{
	// The brief code below illustrates several aspects of the library
	// worth noting:
	//
	// 1. You can subscript a row by integer (position of the field in
	// the row) or by string (name of field in the row).  The former is
	// more efficient, while the latter trades some efficiency for
	// robustness in the face of schema changes.  (Consider using SSQLS
	// if you need a tradeoff in between these two positions.)
	//
	// 2. You can also get at a row's field's with Row::at(), which is
	// much like Row::operator[](int).  Besides the syntax difference,
	// the only practical difference is that only at() can access field
	// 0: this is because '0' can be converted to both int and to const
	// char*, so the compiler rightly complains that it can't decide
	// which overload to call.
	//
	// 3. Notice that we make an explicit temporary copy of the first
	// field, which is the only string field.  We must tolerate the
	// inefficiency of this copy, because Row::operator[] returns a
	// ColData object, which goes away after it is converted to some
	// other form.  So, while we could have made print_stock_row()
	// take a const char* argument (as past versions mistakenly did!)
	// this would result in a dangling pointer, since it points into the
	// ColData object, which is dead by the time the pointer is
	// evaluated in print_stock_row().  It will probably even work this
	// way, but like any memory bug, it can wreak subtle havoc.
	std::string item(row.at(0));
	print_stock_row(item, row["num"], row[2], row[3], row[4]);
}

//// print_stock_rows //////////////////////////////////////////////////
// Print out a number of rows from the example 'stock' table.

void
print_stock_rows(mysqlpp::Result& res)
{
	print_stock_header(res.size());

	// Use the Result class's read-only random access iterator to walk
	// through the query results.
	mysqlpp::Result::iterator i;
	for (i = res.begin(); i != res.end(); ++i) {
		// Notice that a dereferenced result iterator can be converted
		// to a Row object, which makes for easier element access.
		print_stock_row(*i);
	}
}

//// get_stock_table ///////////////////////////////////////////////////
// Retreive the entire contents of the example 'stock' table.

void
get_stock_table(mysqlpp::Query& query, mysqlpp::Result& res)
{
	// Reset the query object, in case we're re-using it.
	query.reset();

	// You can write to the query object like you would any ostream.
	query << "select * from stock";

	// Show the query string.  If you call preview(), it must be before
	// you call execute() or store() or use().
	cout << "Query: " << query.preview() << endl;

	// Execute the query, storing the results in memory.
	res = query.store();
}

//// print_stock_table /////////////////////////////////////////////////
// Simply retrieve and print the entire contents of the stock table.

void
print_stock_table(mysqlpp::Query& query)
{
	mysqlpp::Result res;
	get_stock_table(query, res);
	print_stock_rows(res);
}

//// print_usage ///////////////////////////////////////////////////////
// Show the program's usage message

void
print_usage(const char* program_name, const char* extra_parms)
{
	cout << "usage: " << program_name <<
			" [host [user [password [port]]]] " << extra_parms << endl;
	cout << endl;
	cout << "    If no arguments are given, connects to database "
			"server on localhost" << endl;
	cout << "    using your user name and no password.  You may give "
			"any number of" << endl;
	cout << "    these arguments, but they must be in the order "
			"listed, and you" << endl;
	cout << "    cannot skip preceding arguments." << endl;
	if (strlen(extra_parms) > 0) {
		cout << endl;
		cout << "    The extra parameter " << extra_parms <<
				" is required, regardless of which" << endl;
		cout << "    other arguments you pass." << endl;
	}
	cout << endl;
}

//// connect_to_db /////////////////////////////////////////////////////
// Establishes a connection to a MySQL database server, optionally
// attaching to database kdb.  This is basically a command-line parser
// for the examples, since the example programs' arguments give us the
// information we need to establish the server connection.

bool
connect_to_db(int argc, char *argv[], mysqlpp::Connection& con,
		const char *kdb)
{
	if (argc < 1) {
		cerr << "Bad argument count: " << argc << '!' << endl;
		return false;
	}

	if (!kdb) {
		kdb = kpcSampleDatabase;
	}

	if ((argc > 1) && (argv[1][0] == '-')) {
		print_usage(argv[0]);
		return false;
	}

	if (argc == 1) {
		con.connect(kdb);
	}
	else if (argc == 2) {
		con.connect(kdb, argv[1]);
	}
	else if (argc == 3) {
		con.connect(kdb, argv[1], argv[2]);
	}
	else if (argc == 4) {
		con.connect(kdb, argv[1], argv[2], argv[3]);
	}
	else if (argc >= 5) {
		con.connect(kdb, argv[1], argv[2], argv[3], atoi(argv[4]));
	}

	if (con) {
		return true;
	}
	else {
		cerr << "Database connection failed: " << con.error() << endl;
		return false;
	}
}
<commit_msg>Comment fix<commit_after>/***********************************************************************
 util.cpp - Utility functions required by several of the example
 	programs.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2006 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "util.h"

#include <iostream>
#include <iomanip>

// This include isn't actually needed here.  It's just a test of the
// feature added in v2.1 allowing an SSQLS to be defined in multiple
// modules without having a multiply-defined static variable error.
// The test is disabled for VC++ 2003, which doesn't support the
// feature.
#if !defined(_MSC_VER) || _MSC_VER >= 1400
#	define MYSQLPP_SSQLS_NO_STATICS
#	include "stock.h"
#endif

using namespace std;

const char* kpcSampleDatabase = "mysql_cpp_data";

//// print_stock_header ////////////////////////////////////////////////
// Display a header suitable for use with print_stock_rows().

void
print_stock_header(int rows)
{
	cout << "Records found: " << rows << endl << endl;
	cout.setf(ios::left);
	cout << setw(21) << "Item" <<
			setw(10) << "Num" <<
			setw(10) << "Weight" <<
			setw(10) << "Price" <<
			"Date" << endl << endl;
}

//// print_stock_row ///////////////////////////////////////////////////
// Print out a row of data from the stock table, in a format compatible
// with the header printed out in the previous function.

void
print_stock_row(const mysqlpp::sql_char& item, mysqlpp::sql_bigint num,
		mysqlpp::sql_double weight, mysqlpp::sql_double price,
		const mysqlpp::sql_date& date)
{
	char buf[100];
	cout << setw(20) << item << ' ' <<
			setw(9) << num << ' ' <<
			setw(9) << weight << ' ' <<
			setw(9) << price << ' ' <<
			date << endl;
}

//// print_stock_row ///////////////////////////////////////////////////
// Take a Row from the example 'stock' table, break it up into fields,
// and call the above version of this function.

void
print_stock_row(const mysqlpp::Row& row)
{
	// The brief code below illustrates several aspects of the library
	// worth noting:
	//
	// 1. You can subscript a row by integer (position of the field in
	// the row) or by string (name of field in the row).  The former is
	// more efficient, while the latter trades some efficiency for
	// robustness in the face of schema changes.  (Consider using SSQLS
	// if you need a tradeoff in between these two positions.)
	//
	// 2. You can also get at a row's field's with Row::at(), which is
	// much like Row::operator[](int).  Besides the syntax difference,
	// the only practical difference is that only at() can access field
	// 0: this is because '0' can be converted to both int and to const
	// char*, so the compiler rightly complains that it can't decide
	// which overload to call.
	//
	// 3. Notice that we make an explicit temporary copy of the first
	// field, which is the only string field.  We must tolerate the
	// inefficiency of this copy, because Row::operator[] returns a
	// ColData object, which goes away after it is converted to some
	// other form.  So, while we could have made print_stock_row()
	// take a const char* argument (as past versions mistakenly did!)
	// this would result in a dangling pointer, since it points into the
	// ColData object, which is dead by the time the pointer is
	// evaluated in print_stock_row().  It will probably even work this
	// way, but like any memory bug, it can wreak subtle havoc.
	std::string item(row.at(0));
	print_stock_row(item, row["num"], row[2], row[3], row[4]);
}

//// print_stock_rows //////////////////////////////////////////////////
// Print out a number of rows from the example 'stock' table.

void
print_stock_rows(mysqlpp::Result& res)
{
	print_stock_header(res.size());

	// Use the Result class's read-only random access iterator to walk
	// through the query results.
	mysqlpp::Result::iterator i;
	for (i = res.begin(); i != res.end(); ++i) {
		// Notice that a dereferenced result iterator can be converted
		// to a Row object, which makes for easier element access.
		print_stock_row(*i);
	}
}

//// get_stock_table ///////////////////////////////////////////////////
// Retreive the entire contents of the example 'stock' table.

void
get_stock_table(mysqlpp::Query& query, mysqlpp::Result& res)
{
	// Reset the query object, in case we're re-using it.
	query.reset();

	// You can write to the query object like you would any ostream.
	query << "select * from stock";

	// Show the query string.  If you call preview(), it must be before
	// you call execute() or store() or use().
	cout << "Query: " << query.preview() << endl;

	// Execute the query, storing the results in memory.
	res = query.store();
}

//// print_stock_table /////////////////////////////////////////////////
// Simply retrieve and print the entire contents of the stock table.

void
print_stock_table(mysqlpp::Query& query)
{
	mysqlpp::Result res;
	get_stock_table(query, res);
	print_stock_rows(res);
}

//// print_usage ///////////////////////////////////////////////////////
// Show the program's usage message

void
print_usage(const char* program_name, const char* extra_parms)
{
	cout << "usage: " << program_name <<
			" [host [user [password [port]]]] " << extra_parms << endl;
	cout << endl;
	cout << "    If no arguments are given, connects to database "
			"server on localhost" << endl;
	cout << "    using your user name and no password.  You may give "
			"any number of" << endl;
	cout << "    these arguments, but they must be in the order "
			"listed, and you" << endl;
	cout << "    cannot skip preceding arguments." << endl;
	if (strlen(extra_parms) > 0) {
		cout << endl;
		cout << "    The extra parameter " << extra_parms <<
				" is required, regardless of which" << endl;
		cout << "    other arguments you pass." << endl;
	}
	cout << endl;
}

//// connect_to_db /////////////////////////////////////////////////////
// Establishes a connection to a MySQL database server, optionally
// attaching to database kdb.  This is basically a command-line parser
// for the examples, since the example programs' arguments give us the
// information we need to establish the server connection.

bool
connect_to_db(int argc, char *argv[], mysqlpp::Connection& con,
		const char *kdb)
{
	if (argc < 1) {
		cerr << "Bad argument count: " << argc << '!' << endl;
		return false;
	}

	if (!kdb) {
		kdb = kpcSampleDatabase;
	}

	if ((argc > 1) && (argv[1][0] == '-')) {
		print_usage(argv[0]);
		return false;
	}

	if (argc == 1) {
		con.connect(kdb);
	}
	else if (argc == 2) {
		con.connect(kdb, argv[1]);
	}
	else if (argc == 3) {
		con.connect(kdb, argv[1], argv[2]);
	}
	else if (argc == 4) {
		con.connect(kdb, argv[1], argv[2], argv[3]);
	}
	else if (argc >= 5) {
		con.connect(kdb, argv[1], argv[2], argv[3], atoi(argv[4]));
	}

	if (con) {
		return true;
	}
	else {
		cerr << "Database connection failed: " << con.error() << endl;
		return false;
	}
}
<|endoftext|>


<commit_before>#ifndef EBITEN_SCRIPT_SQUIRREL_GAME_HPP
#define EBITEN_SCRIPT_SQUIRREL_GAME_HPP

#include "ebiten_script/sprite.hpp"
#include "ebiten_script/squirrel/geometry_matrix_funcs.hpp"
#include "ebiten_script/squirrel/texture_funcs.hpp"
#include "ebiten/graphics/graphics_context.hpp"
#include "ebiten/graphics/texture_factory.hpp"
#include "ebiten/noncopyable.hpp"
#include <squirrel.h>
#include <sqstdio.h>
#include <sqstdaux.h>
#include <cstdio>
#include <exception>
#include <string>
#include <iostream>

namespace ebiten_script {
namespace squirrel {

class game : private ebiten::noncopyable {
private:
  HSQUIRRELVM const vm_;
  HSQOBJECT game_;
  ebiten::graphics::texture main_offscreen_ebiten_texture_;
  HSQOBJECT main_offscreen_texture_;
public:
  game(std::string filename)
    : vm_(::sq_open(1024)) {
    ::sqstd_seterrorhandlers(this->vm_);
    ::sq_setprintfunc(this->vm_, print_func, error_func);
    // TODO: load the standard library
    {
      SQInteger const top = ::sq_gettop(this->vm_);
      this->initialize_ebiten_classes();
      ::sq_pushroottable(this->vm_);
      ::sqstd_dofile(this->vm_,
                     _SC(filename.c_str()),
                     SQTrue,
                     SQTrue);
      if (::sq_gettype(this->vm_, -1) == OT_INSTANCE) {
        ::sq_getstackobj(this->vm_, -1, &this->game_);
        ::sq_addref(this->vm_, &this->game_);
      }
      ::sq_settop(this->vm_, top);
    }
    {
      /*
       * [Squirrel]
       * mainOffscreenTexture = ebiten.Texture(0, 0)
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushroottable(this->vm_);
      ::sq_pushstring(this->vm_, _SC("ebiten"), -1);
      if (SQ_FAILED(::sq_get(this->vm_, -2))) {
        assert(false);
      }
      ::sq_pushstring(this->vm_, _SC("Texture"), -1);
      if (SQ_FAILED(::sq_get(this->vm_, -2))) {
        assert(false);
      }
      ::sq_pushroottable(this->vm_);
      ::sq_pushinteger(this->vm_, 0);
      ::sq_pushinteger(this->vm_, 0);
      if (SQ_FAILED(::sq_call(this->vm_, 3, SQTrue, SQTrue))) {
        assert(false);
      }
      assert(::sq_gettype(this->vm_, -1) == OT_INSTANCE);
      ::sq_getstackobj(this->vm_, -1, &this->main_offscreen_texture_);
      ::sq_addref(this->vm_, &this->main_offscreen_texture_);
      ::sq_settop(this->vm_, top);
    }
  }
  virtual
  ~game() {
    ::sq_close(this->vm_);
  }
  void
  update(ebiten::graphics::texture_factory& tf) {
    {
      /*
       * [Squirrel]
       * game.update()
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_pushstring(this->vm_, _SC("update"), -1);
      ::sq_get(this->vm_, -2);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_call(this->vm_, 1, SQFalse, SQTrue);
      ::sq_settop(this->vm_, top);
    }
    texture_funcs::instantiate(this->vm_, tf);
  }
  void
  draw(ebiten::graphics::graphics_context& g,
       ebiten::graphics::texture& main_offscreen) {
    this->main_offscreen_ebiten_texture_ = main_offscreen;
    g.set_offscreen(main_offscreen);
    g.clear();
    {
      /*
       * [Squirrel]
       * mainOffscreenTexture.setTexture_(main_offscreen)
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushobject(this->vm_, this->main_offscreen_texture_);
      ::sq_pushstring(this->vm_, _SC("setTexture_"), -1);
      ::sq_get(this->vm_, -2);
      ::sq_pushobject(this->vm_, this->main_offscreen_texture_);
      SQUserPointer p = reinterpret_cast<SQUserPointer>(&this->main_offscreen_ebiten_texture_);
      ::sq_pushuserpointer(this->vm_, p);
      ::sq_call(this->vm_, 2, SQFalse, SQTrue);
      ::sq_settop(this->vm_, top);
    }
    {
      /*
       * [Squirrel]
       * game.draw(mainOffscreenTexture)
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_pushstring(this->vm_, _SC("draw"), -1);
      ::sq_get(this->vm_, -2);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_pushobject(this->vm_, this->main_offscreen_texture_);
      ::sq_call(this->vm_, 2, SQFalse, SQTrue);
      ::sq_settop(this->vm_, top);
    }
    texture_funcs::flush_texture_commands(this->vm_, g);
  }
private:
  static void
  print_func(HSQUIRRELVM, SQChar const* s, ...) {
    va_list vl;
    ::va_start(vl, s);
    ::vfprintf(stdout, s, vl);
    ::va_end(vl);
  }
  static void
  error_func(HSQUIRRELVM, SQChar const* s, ...) {
    va_list vl;
    ::va_start(vl, s);
    ::vfprintf(stderr, s, vl);
    ::va_end(vl);
    // TODO: throw?
    std::abort();
  }
  void
  initialize_ebiten_classes() {
    static std::string const e("ebiten");
    this->create_table(e);
    {
      static std::string const gm("GeometryMatrix");
      this->create_class(e, gm);
      this->create_method(e, gm,
                          "constructor",
                          geometry_matrix_funcs::constructor,
                          "x",
                          false);
      this->create_method(e, gm,
                          "_tostring",
                          geometry_matrix_funcs::meta_tostring,
                          "x",
                          false);
    }
    {
      static std::string const t("Texture");
      this->create_class(e, t);
      this->create_method(e, t,
                          "constructor",
                          texture_funcs::method_constructor,
                          "",
                          false);
      this->create_method(e, t,
                          "isCreated",
                          texture_funcs::method_is_created,
                          "x",
                          false);
      this->create_method(e, t,
                          "getWidth",
                          texture_funcs::method_get_width,
                          "x",
                          false);
      this->create_method(e, t,
                          "getHeight",
                          texture_funcs::method_get_height,
                          "x",
                          false);
      this->create_method(e, t,
                          "clear",
                          texture_funcs::method_clear,
                          "x",
                          false);
      this->create_method(e, t,
                          "drawRect",
                          texture_funcs::method_draw_rect,
                          "xiiiiiiii",
                          false);
      this->create_method(e, t,
                          "setTexture_",
                          texture_funcs::method_set_texture,
                          "xp",
                          false);
    }
  }
  void
  create_table(std::string const& name) {
    SQInteger const top = ::sq_gettop(this->vm_);
    ::sq_pushroottable(this->vm_);
    ::sq_pushstring(this->vm_, _SC(name.c_str()), -1);
    ::sq_newtable(this->vm_);
    ::sq_newslot(this->vm_, -3, SQFalse);
    ::sq_settop(this->vm_, top);
  }
  void
  create_class(std::string const& namespace_name,
               std::string const& class_name) {
    SQInteger const top = ::sq_gettop(this->vm_);
    ::sq_pushroottable(this->vm_);
    ::sq_pushstring(this->vm_, _SC(namespace_name.c_str()), -1);
    ::sq_get(this->vm_, -2);
    ::sq_pushstring(this->vm_, _SC(class_name.c_str()), -1);
    ::sq_newclass(this->vm_, SQFalse);
    ::sq_newslot(this->vm_, -3, SQFalse);
    ::sq_settop(this->vm_, top);
  }
  void
  create_method(std::string const& namespace_name,
                std::string const& class_name,
                std::string const& method_name,
                SQFUNCTION func,
                std::string const& type_mask,
                bool is_static) {
    SQInteger const top = ::sq_gettop(this->vm_);
    ::sq_pushroottable(this->vm_);
    ::sq_pushstring(this->vm_, _SC(namespace_name.c_str()), -1);
    ::sq_get(this->vm_, -2);
    ::sq_pushstring(this->vm_, _SC(class_name.c_str()), -1);
    ::sq_get(this->vm_, -2);
    ::sq_pushstring(this->vm_, _SC(method_name.c_str()), -1);
    ::sq_newclosure(this->vm_, func, 0);
    if (!type_mask.empty()) {
      ::sq_setparamscheck(this->vm_, type_mask.size(), _SC(type_mask.c_str()));
    }
    ::sq_newslot(this->vm_, -3, is_static);
    ::sq_settop(this->vm_, top);
  }
};

}
}

#endif
<commit_msg>Added comments<commit_after>#ifndef EBITEN_SCRIPT_SQUIRREL_GAME_HPP
#define EBITEN_SCRIPT_SQUIRREL_GAME_HPP

#include "ebiten_script/sprite.hpp"
#include "ebiten_script/squirrel/geometry_matrix_funcs.hpp"
#include "ebiten_script/squirrel/texture_funcs.hpp"
#include "ebiten/graphics/graphics_context.hpp"
#include "ebiten/graphics/texture_factory.hpp"
#include "ebiten/noncopyable.hpp"
#include <squirrel.h>
#include <sqstdio.h>
#include <sqstdaux.h>
#include <cstdio>
#include <exception>
#include <string>
#include <iostream>

namespace ebiten_script {
namespace squirrel {

class game : private ebiten::noncopyable {
private:
  HSQUIRRELVM const vm_;
  HSQOBJECT game_;
  ebiten::graphics::texture main_offscreen_ebiten_texture_;
  HSQOBJECT main_offscreen_texture_;
public:
  game(std::string filename)
    : vm_(::sq_open(1024)) {
    ::sqstd_seterrorhandlers(this->vm_);
    ::sq_setprintfunc(this->vm_, print_func, error_func);
    // TODO: load the standard library
    {
      /*
       * [Squirrel]
       * game = ::dofile(filename)
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      this->initialize_ebiten_classes();
      ::sq_pushroottable(this->vm_);
      ::sqstd_dofile(this->vm_,
                     _SC(filename.c_str()),
                     SQTrue,
                     SQTrue);
      if (::sq_gettype(this->vm_, -1) == OT_INSTANCE) {
        ::sq_getstackobj(this->vm_, -1, &this->game_);
        ::sq_addref(this->vm_, &this->game_);
      }
      ::sq_settop(this->vm_, top);
    }
    {
      /*
       * [Squirrel]
       * mainOffscreenTexture = ebiten.Texture(0, 0)
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushroottable(this->vm_);
      ::sq_pushstring(this->vm_, _SC("ebiten"), -1);
      if (SQ_FAILED(::sq_get(this->vm_, -2))) {
        assert(false);
      }
      ::sq_pushstring(this->vm_, _SC("Texture"), -1);
      if (SQ_FAILED(::sq_get(this->vm_, -2))) {
        assert(false);
      }
      ::sq_pushroottable(this->vm_);
      ::sq_pushinteger(this->vm_, 0);
      ::sq_pushinteger(this->vm_, 0);
      if (SQ_FAILED(::sq_call(this->vm_, 3, SQTrue, SQTrue))) {
        assert(false);
      }
      assert(::sq_gettype(this->vm_, -1) == OT_INSTANCE);
      ::sq_getstackobj(this->vm_, -1, &this->main_offscreen_texture_);
      ::sq_addref(this->vm_, &this->main_offscreen_texture_);
      ::sq_settop(this->vm_, top);
    }
  }
  virtual
  ~game() {
    ::sq_close(this->vm_);
  }
  void
  update(ebiten::graphics::texture_factory& tf) {
    {
      /*
       * [Squirrel]
       * game.update()
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_pushstring(this->vm_, _SC("update"), -1);
      ::sq_get(this->vm_, -2);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_call(this->vm_, 1, SQFalse, SQTrue);
      ::sq_settop(this->vm_, top);
    }
    texture_funcs::instantiate(this->vm_, tf);
  }
  void
  draw(ebiten::graphics::graphics_context& g,
       ebiten::graphics::texture& main_offscreen) {
    this->main_offscreen_ebiten_texture_ = main_offscreen;
    g.set_offscreen(main_offscreen);
    g.clear();
    {
      /*
       * [Squirrel]
       * mainOffscreenTexture.setTexture_(main_offscreen)
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushobject(this->vm_, this->main_offscreen_texture_);
      ::sq_pushstring(this->vm_, _SC("setTexture_"), -1);
      ::sq_get(this->vm_, -2);
      ::sq_pushobject(this->vm_, this->main_offscreen_texture_);
      SQUserPointer p = reinterpret_cast<SQUserPointer>(&this->main_offscreen_ebiten_texture_);
      ::sq_pushuserpointer(this->vm_, p);
      ::sq_call(this->vm_, 2, SQFalse, SQTrue);
      ::sq_settop(this->vm_, top);
    }
    {
      /*
       * [Squirrel]
       * game.draw(mainOffscreenTexture)
       */
      SQInteger const top = ::sq_gettop(this->vm_);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_pushstring(this->vm_, _SC("draw"), -1);
      ::sq_get(this->vm_, -2);
      ::sq_pushobject(this->vm_, this->game_);
      ::sq_pushobject(this->vm_, this->main_offscreen_texture_);
      ::sq_call(this->vm_, 2, SQFalse, SQTrue);
      ::sq_settop(this->vm_, top);
    }
    texture_funcs::flush_texture_commands(this->vm_, g);
  }
private:
  static void
  print_func(HSQUIRRELVM, SQChar const* s, ...) {
    va_list vl;
    ::va_start(vl, s);
    ::vfprintf(stdout, s, vl);
    ::va_end(vl);
  }
  static void
  error_func(HSQUIRRELVM, SQChar const* s, ...) {
    va_list vl;
    ::va_start(vl, s);
    ::vfprintf(stderr, s, vl);
    ::va_end(vl);
    // TODO: throw?
    std::abort();
  }
  void
  initialize_ebiten_classes() {
    static std::string const e("ebiten");
    this->create_table(e);
    {
      static std::string const gm("GeometryMatrix");
      this->create_class(e, gm);
      this->create_method(e, gm,
                          "constructor",
                          geometry_matrix_funcs::constructor,
                          "x",
                          false);
      this->create_method(e, gm,
                          "_tostring",
                          geometry_matrix_funcs::meta_tostring,
                          "x",
                          false);
    }
    {
      static std::string const t("Texture");
      this->create_class(e, t);
      this->create_method(e, t,
                          "constructor",
                          texture_funcs::method_constructor,
                          "",
                          false);
      this->create_method(e, t,
                          "isCreated",
                          texture_funcs::method_is_created,
                          "x",
                          false);
      this->create_method(e, t,
                          "getWidth",
                          texture_funcs::method_get_width,
                          "x",
                          false);
      this->create_method(e, t,
                          "getHeight",
                          texture_funcs::method_get_height,
                          "x",
                          false);
      this->create_method(e, t,
                          "clear",
                          texture_funcs::method_clear,
                          "x",
                          false);
      this->create_method(e, t,
                          "drawRect",
                          texture_funcs::method_draw_rect,
                          "xiiiiiiii",
                          false);
      this->create_method(e, t,
                          "setTexture_",
                          texture_funcs::method_set_texture,
                          "xp",
                          false);
    }
  }
  void
  create_table(std::string const& name) {
    SQInteger const top = ::sq_gettop(this->vm_);
    ::sq_pushroottable(this->vm_);
    ::sq_pushstring(this->vm_, _SC(name.c_str()), -1);
    ::sq_newtable(this->vm_);
    ::sq_newslot(this->vm_, -3, SQFalse);
    ::sq_settop(this->vm_, top);
  }
  void
  create_class(std::string const& namespace_name,
               std::string const& class_name) {
    SQInteger const top = ::sq_gettop(this->vm_);
    ::sq_pushroottable(this->vm_);
    ::sq_pushstring(this->vm_, _SC(namespace_name.c_str()), -1);
    ::sq_get(this->vm_, -2);
    ::sq_pushstring(this->vm_, _SC(class_name.c_str()), -1);
    ::sq_newclass(this->vm_, SQFalse);
    ::sq_newslot(this->vm_, -3, SQFalse);
    ::sq_settop(this->vm_, top);
  }
  void
  create_method(std::string const& namespace_name,
                std::string const& class_name,
                std::string const& method_name,
                SQFUNCTION func,
                std::string const& type_mask,
                bool is_static) {
    SQInteger const top = ::sq_gettop(this->vm_);
    ::sq_pushroottable(this->vm_);
    ::sq_pushstring(this->vm_, _SC(namespace_name.c_str()), -1);
    ::sq_get(this->vm_, -2);
    ::sq_pushstring(this->vm_, _SC(class_name.c_str()), -1);
    ::sq_get(this->vm_, -2);
    ::sq_pushstring(this->vm_, _SC(method_name.c_str()), -1);
    ::sq_newclosure(this->vm_, func, 0);
    if (!type_mask.empty()) {
      ::sq_setparamscheck(this->vm_, type_mask.size(), _SC(type_mask.c_str()));
    }
    ::sq_newslot(this->vm_, -3, is_static);
    ::sq_settop(this->vm_, top);
  }
};

}
}

#endif
<|endoftext|>


<commit_before>// sample.cxx -- Sound sample encapsulation class
//
// Written by Curtis Olson, started April 2004.
//
// Copyright (C) 2004  Curtis L. Olson - curt@flightgear.org
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$

#if defined( __APPLE__ )
# define AL_ILLEGAL_ENUM AL_INVALID_ENUM
# define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION
# include <OpenAL/al.h>
# include <OpenAL/alut.h>
#else
# include <AL/al.h>
# include <AL/alut.h>
#endif

#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/exception.hxx>

#include "sample_openal.hxx"

//
// SGSoundSample
//

static void print_openal_error( ALuint error ) {
    if ( error == AL_INVALID_NAME ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_INVALID_NAME" );
    } else if ( error == AL_ILLEGAL_ENUM ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_ILLEGAL_ENUM" );
    } else if ( error == AL_INVALID_VALUE ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_INVALID_VALUE" );
    } else if ( error == AL_ILLEGAL_COMMAND ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_ILLEGAL_COMMAND" );
    } else if ( error == AL_OUT_OF_MEMORY ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_OUT_OF_MEMORY" );
    } else {
        SG_LOG( SG_GENERAL, SG_ALERT, "Unhandled error code = " << error );
    }
}

// constructor
SGSoundSample::SGSoundSample( const char *path, const char *file ) :
    pitch(1.0),
    volume(1.0),
    loop(AL_FALSE)
{
    SGPath samplepath( path );
    if ( strlen(file) ) {
        samplepath.append( file );
    }

    SG_LOG( SG_GENERAL, SG_ALERT, "From file sounds sample = "
            << samplepath.str() );

    ALuint error;

    source_pos[0] = 0.0; source_pos[1] = 0.0; source_pos[2] = 0.0;
    source_vel[0] = 0.0; source_vel[1] = 0.0; source_vel[2] = 0.0;

    // clear errors from elsewhere?
    alGetError();

    // create an OpenAL buffer handle
    alGenBuffers(1, &buffer);
    error = alGetError();
    if ( error != AL_NO_ERROR ) {
        print_openal_error( error );
        throw sg_exception("Failed to gen OpenAL buffer.");
    } else {
        SG_LOG( SG_GENERAL, SG_ALERT, "Buffer created ok!" );
    }

    // Load the sample file
#if defined (__APPLE__)
    alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
                     &format, &data, &size, &freq );
#else
    alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
                     &format, &data, &size, &freq, &loop );
#endif
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to load wav file.");
    }

    // Copy data to the internal OpenAL buffer
    alBufferData( buffer, format, data, size, freq );
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to buffer data.");
    }

    alutUnloadWAV( format, data, size, freq );

    // Bind buffer with a source.
    alGenSources(1, &source);
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to gen source.");
    }

    alSourcei( source, AL_BUFFER, buffer );
    alSourcef( source, AL_PITCH, pitch );
    alSourcef( source, AL_GAIN, volume );
    alSourcefv( source, AL_POSITION, source_pos );
    alSourcefv( source, AL_VELOCITY, source_vel );
    alSourcei( source, AL_LOOPING, loop );
}

// constructor
SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq ) :
    pitch(1.0),
    volume(1.0),
    loop(AL_FALSE)
{
    SG_LOG( SG_GENERAL, SG_ALERT, "In memory sounds sample" );

    source_pos[0] = 0.0; source_pos[1] = 0.0; source_pos[2] = 0.0;
    source_vel[0] = 0.0; source_vel[1] = 0.0; source_vel[2] = 0.0;

    // Load wav data into a buffer.
    alGenBuffers(1, &buffer);
    if (alGetError() != AL_NO_ERROR) {
        SG_LOG( SG_GENERAL, SG_ALERT, "Error in alGenBuffers()" );
        return;
    }

    format = AL_FORMAT_MONO8;
    size = len;
    data = _data;
    freq = _freq;

    alBufferData( buffer, format, data, size, freq );

    // Bind buffer with a source.
    alGenSources(1, &source);
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to gen source.");
    }

    alSourcei( source, AL_BUFFER, buffer );
    alSourcef( source, AL_PITCH, pitch );
    alSourcef( source, AL_GAIN, volume );
    alSourcefv( source, AL_POSITION, source_pos );
    alSourcefv( source, AL_VELOCITY, source_vel );
    alSourcei( source, AL_LOOPING, loop );
}

// destructor
SGSoundSample::~SGSoundSample() {
    SG_LOG( SG_GENERAL, SG_ALERT, "Deleting a sample" );
    alDeleteSources(1, &source);
    alDeleteBuffers(1, &buffer);
}

// play the sample
void SGSoundSample::play( bool _loop ) {
    loop = _loop;

    // make sure sound isn't already playing
    alSourceStop( source );

    alSourcei( source, AL_LOOPING, loop );
    alSourcePlay( source );
}

// stop playing the sample
void SGSoundSample::stop() {
    alSourceStop( source );
}
<commit_msg>Lower verbosity.<commit_after>// sample.cxx -- Sound sample encapsulation class
//
// Written by Curtis Olson, started April 2004.
//
// Copyright (C) 2004  Curtis L. Olson - curt@flightgear.org
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$

#if defined( __APPLE__ )
# define AL_ILLEGAL_ENUM AL_INVALID_ENUM
# define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION
# include <OpenAL/al.h>
# include <OpenAL/alut.h>
#else
# include <AL/al.h>
# include <AL/alut.h>
#endif

#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/exception.hxx>

#include "sample_openal.hxx"

//
// SGSoundSample
//

static void print_openal_error( ALuint error ) {
    if ( error == AL_INVALID_NAME ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_INVALID_NAME" );
    } else if ( error == AL_ILLEGAL_ENUM ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_ILLEGAL_ENUM" );
    } else if ( error == AL_INVALID_VALUE ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_INVALID_VALUE" );
    } else if ( error == AL_ILLEGAL_COMMAND ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_ILLEGAL_COMMAND" );
    } else if ( error == AL_OUT_OF_MEMORY ) {
        SG_LOG( SG_GENERAL, SG_ALERT, "AL_OUT_OF_MEMORY" );
    } else {
        SG_LOG( SG_GENERAL, SG_ALERT, "Unhandled error code = " << error );
    }
}

// constructor
SGSoundSample::SGSoundSample( const char *path, const char *file ) :
    pitch(1.0),
    volume(1.0),
    loop(AL_FALSE)
{
    SGPath samplepath( path );
    if ( strlen(file) ) {
        samplepath.append( file );
    }

    SG_LOG( SG_GENERAL, SG_ALERT, "From file sounds sample = "
            << samplepath.str() );

    ALuint error;

    source_pos[0] = 0.0; source_pos[1] = 0.0; source_pos[2] = 0.0;
    source_vel[0] = 0.0; source_vel[1] = 0.0; source_vel[2] = 0.0;

    // clear errors from elsewhere?
    alGetError();

    // create an OpenAL buffer handle
    alGenBuffers(1, &buffer);
    error = alGetError();
    if ( error != AL_NO_ERROR ) {
        print_openal_error( error );
        throw sg_exception("Failed to gen OpenAL buffer.");
    } else {
        SG_LOG( SG_GENERAL, SG_ALERT, "Buffer created ok!" );
    }

    // Load the sample file
#if defined (__APPLE__)
    alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
                     &format, &data, &size, &freq );
#else
    alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
                     &format, &data, &size, &freq, &loop );
#endif
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to load wav file.");
    }

    // Copy data to the internal OpenAL buffer
    alBufferData( buffer, format, data, size, freq );
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to buffer data.");
    }

    alutUnloadWAV( format, data, size, freq );

    // Bind buffer with a source.
    alGenSources(1, &source);
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to gen source.");
    }

    alSourcei( source, AL_BUFFER, buffer );
    alSourcef( source, AL_PITCH, pitch );
    alSourcef( source, AL_GAIN, volume );
    alSourcefv( source, AL_POSITION, source_pos );
    alSourcefv( source, AL_VELOCITY, source_vel );
    alSourcei( source, AL_LOOPING, loop );
}

// constructor
SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq ) :
    pitch(1.0),
    volume(1.0),
    loop(AL_FALSE)
{
    SG_LOG( SG_GENERAL, SG_ALERT, "In memory sounds sample" );

    source_pos[0] = 0.0; source_pos[1] = 0.0; source_pos[2] = 0.0;
    source_vel[0] = 0.0; source_vel[1] = 0.0; source_vel[2] = 0.0;

    // Load wav data into a buffer.
    alGenBuffers(1, &buffer);
    if (alGetError() != AL_NO_ERROR) {
        SG_LOG( SG_GENERAL, SG_ALERT, "Error in alGenBuffers()" );
        return;
    }

    format = AL_FORMAT_MONO8;
    size = len;
    data = _data;
    freq = _freq;

    alBufferData( buffer, format, data, size, freq );

    // Bind buffer with a source.
    alGenSources(1, &source);
    if (alGetError() != AL_NO_ERROR) {
        throw sg_exception("Failed to gen source.");
    }

    alSourcei( source, AL_BUFFER, buffer );
    alSourcef( source, AL_PITCH, pitch );
    alSourcef( source, AL_GAIN, volume );
    alSourcefv( source, AL_POSITION, source_pos );
    alSourcefv( source, AL_VELOCITY, source_vel );
    alSourcei( source, AL_LOOPING, loop );
}

// destructor
SGSoundSample::~SGSoundSample() {
    SG_LOG( SG_GENERAL, SG_INFO, "Deleting a sample" );
    alDeleteSources(1, &source);
    alDeleteBuffers(1, &buffer);
}

// play the sample
void SGSoundSample::play( bool _loop ) {
    loop = _loop;

    // make sure sound isn't already playing
    alSourceStop( source );

    alSourcei( source, AL_LOOPING, loop );
    alSourcePlay( source );
}

// stop playing the sample
void SGSoundSample::stop() {
    alSourceStop( source );
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "bvh_builder_twolevel.h"
#include "bvh_statistics.h"
#include "../builders/bvh_builder_sah.h"
#include "../common/scene_line_segments.h"
#include "../common/scene_triangle_mesh.h"
#include "../common/scene_quad_mesh.h"

#define PROFILE 0

/* new open/merge builder */
#define ENABLE_DIRECT_SAH_MERGE_BUILDER 1

#define SPLIT_MEMORY_RESERVE_FACTOR 1000
#define SPLIT_MEMORY_RESERVE_SCALE 2
#define SPLIT_MIN_EXT_SPACE 1000

// for non-opening two-level approach set ENABLE_DIRECT_SAH_MERGE_BUILDER and ENABLE_OPEN_SEQUENTIAL to 0

/* sequential opening phase in old code path */
#define MAX_OPEN_SIZE 10000
#define ENABLE_OPEN_SEQUENTIAL 0

namespace embree
{
  namespace isa
  {
    template<int N, typename Mesh>
    BVHNBuilderTwoLevel<N,Mesh>::BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, const createMeshAccelTy createMeshAccel, const size_t singleThreadThreshold)
      : bvh(bvh), objects(bvh->objects), scene(scene), createMeshAccel(createMeshAccel), refs(scene->device,0), prims(scene->device,0), singleThreadThreshold(singleThreadThreshold) {}

    template<int N, typename Mesh>
    BVHNBuilderTwoLevel<N,Mesh>::~BVHNBuilderTwoLevel ()
    {
      for (size_t i=0; i<builders.size(); i++)
	delete builders[i];
    }

    // ===========================================================================
    // ===========================================================================
    // ===========================================================================

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::build()
    {
      /* delete some objects */
      size_t num = scene->size();
      if (num < objects.size()) {
        parallel_for(num, objects.size(), [&] (const range<size_t>& r) {
            for (size_t i=r.begin(); i<r.end(); i++) {
              delete builders[i]; builders[i] = nullptr;
              delete objects[i]; objects[i] = nullptr;
            }
          });
      }

#if PROFILE == 1
      while(1)
#endif
      {
      /* reset memory allocator */
      bvh->alloc.reset();

      /* skip build for empty scene */
      const size_t numPrimitives = scene->getNumPrimitives<Mesh,false>();

      if (numPrimitives == 0) {
        prims.resize(0);
        bvh->set(BVH::emptyNode,empty,0);
        return;
      }

      double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderTwoLevel");

      /* resize object array if scene got larger */
      if (objects.size()  < num) objects.resize(num);
      if (builders.size() < num) builders.resize(num);
      if (refs.size()     < num) refs.resize(num);
      nextRef.store(0);

      /* create of acceleration structures */
      parallel_for(size_t(0), num, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          Mesh* mesh = scene->getSafe<Mesh>(objectID);

          /* verify meshes got deleted properly */
          if (mesh == nullptr || mesh->numTimeSteps != 1) {
            assert(objectID < objects.size () && objects[objectID] == nullptr);
            assert(objectID < builders.size() && builders[objectID] == nullptr);
            continue;
          }

          /* create BVH and builder for new meshes */
          if (objects[objectID] == nullptr)
            createMeshAccel(mesh,(AccelData*&)objects[objectID],builders[objectID]);
        }
      });
      /* count total primitive count of all objects */
      std::atomic<int> totalPrims(0);

      /* parallel build of acceleration structures */
      parallel_for(size_t(0), num, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          /* ignore if no triangle mesh or not enabled */
          Mesh* mesh = scene->getSafe<Mesh>(objectID);
          if (mesh == nullptr || !mesh->isEnabled() || mesh->numTimeSteps != 1)
            continue;

          BVH*     object  = objects [objectID]; assert(object);
          Builder* builder = builders[objectID]; assert(builder);

          /* build object if it got modified */
          if (mesh->isModified())
            builder->build();

          /* create build primitive */
          if (!object->getBounds().empty())
          {
#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 1
            refs[nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root,objectID,mesh->size());
            totalPrims += mesh->size();
#else
            refs[nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root);
#endif
          }
        }
      });

#if PROFILE
      double d0 = getSeconds();
#endif
      /* fast path for single geometry scenes */
      if (nextRef == 1) {
        bvh->set(refs[0].node,LBBox3fa(refs[0].bounds()),numPrimitives);
      }

      else
      {
        /* open all large nodes */
        refs.resize(nextRef);

#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 0

#if ENABLE_OPEN_SEQUENTIAL == 1
        open_sequential(numPrimitives,MAX_OPEN_SIZE);
#endif
        /* compute PrimRefs */
        prims.resize(refs.size());
#else

#endif

        bvh->alloc.init_estimate(refs.size()*SPLIT_MEMORY_RESERVE_FACTOR*sizeof(PrimRef)); // FIXME: increase estimate for opening case
        //bvh->alloc.init_estimate(totalPrims.load() * sizeof(PrimRef));

#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
        tbb::task_arena limited(min(32,(int)TaskScheduler::threadCount()));
        limited.execute([&]
#endif
        {
#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 1

          const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(),  PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {

              PrimInfo pinfo(empty);
              for (size_t i=r.begin(); i<r.end(); i++) {
                pinfo.add(refs[i].bounds(),refs[i].bounds().center2());
              }
              return pinfo;
            }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });

#else
          const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(),  PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {

              PrimInfo pinfo(empty);
              for (size_t i=r.begin(); i<r.end(); i++) {
                pinfo.add(refs[i].bounds());
                prims[i] = PrimRef(refs[i].bounds(),(size_t)refs[i].node);
              }
              return pinfo;
            }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
#endif

          /* skip if all objects where empty */
          if (pinfo.size() == 0)
            bvh->set(BVH::emptyNode,empty,0);

          /* otherwise build toplevel hierarchy */
          else
          {
            /* settings for BVH build */
            GeneralBVHBuilder::Settings settings;
            settings.branchingFactor = N;
            settings.maxDepth = BVH::maxBuildDepthLeaf;
            settings.logBlockSize = __bsr(N);
            settings.minLeafSize = 1;
            settings.maxLeafSize = 1;
            settings.travCost = 1.0f;
            settings.intCost = 1.0f;
            settings.singleThreadThreshold = singleThreadThreshold;

#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 1
            /* this probably needs some more tuning */
            const size_t extSize = max(max((size_t)SPLIT_MIN_EXT_SPACE,refs.size()*SPLIT_MEMORY_RESERVE_SCALE),size_t((float)numPrimitives / SPLIT_MEMORY_RESERVE_FACTOR));
            refs.resize(extSize);

            NodeRef root = BVHBuilderBinnedOpenMergeSAH::build<NodeRef,BuildRef>(
              typename BVH::CreateAlloc(bvh),
              typename BVH::AlignedNode::Create2(),
              typename BVH::AlignedNode::Set2(),

              [&] (const BVHBuilderBinnedOpenMergeSAH::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) -> NodeRef  {
                assert(current.prims.size() == 1);
                return (NodeRef) refs[current.prims.begin()].node;
              },
              [&] (BuildRef &bref, BuildRef *refs) -> size_t {
                return openBuildRef(bref,refs);
              },
              [&] (size_t dn) { bvh->scene->progressMonitor(0); },
              refs.data(),extSize,pinfo,settings);
#else
            NodeRef root = BVHBuilderBinnedSAH::build<NodeRef>(
              typename BVH::CreateAlloc(bvh),
              typename BVH::AlignedNode::Create2(),
              typename BVH::AlignedNode::Set2(),

              [&] (const BVHBuilderBinnedSAH::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) -> NodeRef {
                assert(current.prims.size() == 1);
                return (NodeRef) prims[current.prims.begin()].ID();
              },
              [&] (size_t dn) { bvh->scene->progressMonitor(0); },
              prims.data(),pinfo,settings);
#endif

            bvh->set(root,LBBox3fa(pinfo.geomBounds),numPrimitives);
          }
        }
#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
          );
#endif

      }

      bvh->alloc.cleanup();
      bvh->postBuild(t0);
#if PROFILE
      double d1 = getSeconds();
      std::cout << "TOP_LEVEL OPENING/REBUILD TIME " << 1000.0*(d1-d0) << " ms" << std::endl;
#endif
      }

    }

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::deleteGeometry(size_t geomID)
    {
      if (geomID >= objects.size()) return;
      delete builders[geomID]; builders[geomID] = nullptr;
      delete objects [geomID]; objects [geomID] = nullptr;
    }

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::clear()
    {
      for (size_t i=0; i<objects.size(); i++)
        if (objects[i]) objects[i]->clear();

      for (size_t i=0; i<builders.size(); i++)
	if (builders[i]) builders[i]->clear();

      refs.clear();
    }

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::open_sequential(const size_t numPrimitives, const size_t maxOpenSize)
    {
      if (refs.size() == 0)
	return;

      size_t num = min(numPrimitives/400,maxOpenSize);
      refs.reserve(num);

#if 1
      for (size_t i=0;i<refs.size();i++)
      {
        NodeRef ref = refs[i].node;
        if (ref.isAlignedNode())
          ref.prefetch();
      }
#endif

      std::make_heap(refs.begin(),refs.end());
      while (refs.size()+3 <= num)
      {
        std::pop_heap (refs.begin(),refs.end());
        NodeRef ref = refs.back().node;
        if (ref.isLeaf()) break;
        refs.pop_back();

        AlignedNode* node = ref.alignedNode();
        for (size_t i=0; i<N; i++) {
          if (node->child(i) == BVH::emptyNode) continue;
          refs.push_back(BuildRef(node->bounds(i),node->child(i)));

#if 1
          NodeRef ref_pre = node->child(i);
          if (ref_pre.isAlignedNode())
            ref_pre.prefetch();
#endif
          std::push_heap (refs.begin(),refs.end());
        }
      }
    }

#if defined(EMBREE_GEOMETRY_LINES)
    Builder* BVH4BuilderTwoLevelLineSegmentsSAH (void* bvh, Scene* scene, const createLineSegmentsAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<4,LineSegments>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_TRIANGLES)
    Builder* BVH4BuilderTwoLevelTriangleMeshSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<4,TriangleMesh>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_QUADS)
    Builder* BVH4BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, const createQuadMeshAccelTy createMeshAccel) {
    return new BVHNBuilderTwoLevel<4,QuadMesh>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_USER)
    Builder* BVH4BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, const createAccelSetAccelTy createMeshAccel) {
    return new BVHNBuilderTwoLevel<4,AccelSet>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(__AVX__)
#if defined(EMBREE_GEOMETRY_TRIANGLES)
    Builder* BVH8BuilderTwoLevelTriangleMeshSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<8,TriangleMesh>((BVH8*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_QUADS)
    Builder* BVH8BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, const createQuadMeshAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<8,QuadMesh>((BVH8*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_USER)
    Builder* BVH8BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, const createAccelSetAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<8,AccelSet>((BVH8*)bvh,scene,createMeshAccel);
    }
#endif
#endif
  }
}
<commit_msg>added some comments<commit_after>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "bvh_builder_twolevel.h"
#include "bvh_statistics.h"
#include "../builders/bvh_builder_sah.h"
#include "../common/scene_line_segments.h"
#include "../common/scene_triangle_mesh.h"
#include "../common/scene_quad_mesh.h"

#define PROFILE 0

/* new open/merge builder */
#define ENABLE_DIRECT_SAH_MERGE_BUILDER 1

#define SPLIT_MEMORY_RESERVE_FACTOR 1000
#define SPLIT_MEMORY_RESERVE_SCALE 2
#define SPLIT_MIN_EXT_SPACE 1000

/* for non-opening two-level approach set ENABLE_DIRECT_SAH_MERGE_BUILDER and ENABLE_OPEN_SEQUENTIAL to 0 */
/* sequential opening phase in old code path */

#define MAX_OPEN_SIZE 10000
#define ENABLE_OPEN_SEQUENTIAL 0

namespace embree
{
  namespace isa
  {
    template<int N, typename Mesh>
    BVHNBuilderTwoLevel<N,Mesh>::BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, const createMeshAccelTy createMeshAccel, const size_t singleThreadThreshold)
      : bvh(bvh), objects(bvh->objects), scene(scene), createMeshAccel(createMeshAccel), refs(scene->device,0), prims(scene->device,0), singleThreadThreshold(singleThreadThreshold) {}

    template<int N, typename Mesh>
    BVHNBuilderTwoLevel<N,Mesh>::~BVHNBuilderTwoLevel ()
    {
      for (size_t i=0; i<builders.size(); i++)
	delete builders[i];
    }

    // ===========================================================================
    // ===========================================================================
    // ===========================================================================

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::build()
    {
      /* delete some objects */
      size_t num = scene->size();
      if (num < objects.size()) {
        parallel_for(num, objects.size(), [&] (const range<size_t>& r) {
            for (size_t i=r.begin(); i<r.end(); i++) {
              delete builders[i]; builders[i] = nullptr;
              delete objects[i]; objects[i] = nullptr;
            }
          });
      }

#if PROFILE == 1
      while(1)
#endif
      {
      /* reset memory allocator */
      bvh->alloc.reset();

      /* skip build for empty scene */
      const size_t numPrimitives = scene->getNumPrimitives<Mesh,false>();

      if (numPrimitives == 0) {
        prims.resize(0);
        bvh->set(BVH::emptyNode,empty,0);
        return;
      }

      double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderTwoLevel");

      /* resize object array if scene got larger */
      if (objects.size()  < num) objects.resize(num);
      if (builders.size() < num) builders.resize(num);
      if (refs.size()     < num) refs.resize(num);
      nextRef.store(0);

      /* create of acceleration structures */
      parallel_for(size_t(0), num, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          Mesh* mesh = scene->getSafe<Mesh>(objectID);

          /* verify meshes got deleted properly */
          if (mesh == nullptr || mesh->numTimeSteps != 1) {
            assert(objectID < objects.size () && objects[objectID] == nullptr);
            assert(objectID < builders.size() && builders[objectID] == nullptr);
            continue;
          }

          /* create BVH and builder for new meshes */
          if (objects[objectID] == nullptr)
            createMeshAccel(mesh,(AccelData*&)objects[objectID],builders[objectID]);
        }
      });
      /* count total primitive count of all objects */
      std::atomic<int> totalPrims(0);

      /* parallel build of acceleration structures */
      parallel_for(size_t(0), num, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          /* ignore if no triangle mesh or not enabled */
          Mesh* mesh = scene->getSafe<Mesh>(objectID);
          if (mesh == nullptr || !mesh->isEnabled() || mesh->numTimeSteps != 1)
            continue;

          BVH*     object  = objects [objectID]; assert(object);
          Builder* builder = builders[objectID]; assert(builder);

          /* build object if it got modified */
          if (mesh->isModified())
            builder->build();

          /* create build primitive */
          if (!object->getBounds().empty())
          {
#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 1
            refs[nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root,objectID,mesh->size());
            totalPrims += mesh->size();
#else
            refs[nextRef++] = BVHNBuilderTwoLevel::BuildRef(object->getBounds(),object->root);
#endif
          }
        }
      });

#if PROFILE
      double d0 = getSeconds();
#endif
      /* fast path for single geometry scenes */
      if (nextRef == 1) {
        bvh->set(refs[0].node,LBBox3fa(refs[0].bounds()),numPrimitives);
      }

      else
      {
        /* open all large nodes */
        refs.resize(nextRef);

#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 0

#if ENABLE_OPEN_SEQUENTIAL == 1
        open_sequential(numPrimitives,MAX_OPEN_SIZE);
#endif
        /* compute PrimRefs */
        prims.resize(refs.size());
#else

#endif

        // FIXME: find a resonable estimate with respect to the conservative memory allocator
        bvh->alloc.init_estimate(refs.size()*SPLIT_MEMORY_RESERVE_FACTOR*sizeof(PrimRef));
        //bvh->alloc.init_estimate(totalPrims.load() * sizeof(PrimRef));

#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
        tbb::task_arena limited(min(32,(int)TaskScheduler::threadCount()));
        limited.execute([&]
#endif
        {
#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 1

          const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(),  PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {

              PrimInfo pinfo(empty);
              for (size_t i=r.begin(); i<r.end(); i++) {
                pinfo.add(refs[i].bounds(),refs[i].bounds().center2());
              }
              return pinfo;
            }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });

#else
          const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(),  PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo {

              PrimInfo pinfo(empty);
              for (size_t i=r.begin(); i<r.end(); i++) {
                pinfo.add(refs[i].bounds());
                prims[i] = PrimRef(refs[i].bounds(),(size_t)refs[i].node);
              }
              return pinfo;
            }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });
#endif

          /* skip if all objects where empty */
          if (pinfo.size() == 0)
            bvh->set(BVH::emptyNode,empty,0);

          /* otherwise build toplevel hierarchy */
          else
          {
            /* settings for BVH build */
            GeneralBVHBuilder::Settings settings;
            settings.branchingFactor = N;
            settings.maxDepth = BVH::maxBuildDepthLeaf;
            settings.logBlockSize = __bsr(N);
            settings.minLeafSize = 1;
            settings.maxLeafSize = 1;
            settings.travCost = 1.0f;
            settings.intCost = 1.0f;
            settings.singleThreadThreshold = singleThreadThreshold;

#if ENABLE_DIRECT_SAH_MERGE_BUILDER == 1
            /* this probably needs some more tuning */
            const size_t extSize = max(max((size_t)SPLIT_MIN_EXT_SPACE,refs.size()*SPLIT_MEMORY_RESERVE_SCALE),size_t((float)numPrimitives / SPLIT_MEMORY_RESERVE_FACTOR));
            refs.resize(extSize);

            NodeRef root = BVHBuilderBinnedOpenMergeSAH::build<NodeRef,BuildRef>(
              typename BVH::CreateAlloc(bvh),
              typename BVH::AlignedNode::Create2(),
              typename BVH::AlignedNode::Set2(),

              [&] (const BVHBuilderBinnedOpenMergeSAH::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) -> NodeRef  {
                assert(current.prims.size() == 1);
                return (NodeRef) refs[current.prims.begin()].node;
              },
              [&] (BuildRef &bref, BuildRef *refs) -> size_t {
                return openBuildRef(bref,refs);
              },
              [&] (size_t dn) { bvh->scene->progressMonitor(0); },
              refs.data(),extSize,pinfo,settings);
#else
            NodeRef root = BVHBuilderBinnedSAH::build<NodeRef>(
              typename BVH::CreateAlloc(bvh),
              typename BVH::AlignedNode::Create2(),
              typename BVH::AlignedNode::Set2(),

              [&] (const BVHBuilderBinnedSAH::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) -> NodeRef {
                assert(current.prims.size() == 1);
                return (NodeRef) prims[current.prims.begin()].ID();
              },
              [&] (size_t dn) { bvh->scene->progressMonitor(0); },
              prims.data(),pinfo,settings);
#endif

            bvh->set(root,LBBox3fa(pinfo.geomBounds),numPrimitives);
          }
        }
#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL
          );
#endif

      }

      bvh->alloc.cleanup();
      bvh->postBuild(t0);
#if PROFILE
      double d1 = getSeconds();
      std::cout << "TOP_LEVEL OPENING/REBUILD TIME " << 1000.0*(d1-d0) << " ms" << std::endl;
#endif
      }

    }

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::deleteGeometry(size_t geomID)
    {
      if (geomID >= objects.size()) return;
      delete builders[geomID]; builders[geomID] = nullptr;
      delete objects [geomID]; objects [geomID] = nullptr;
    }

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::clear()
    {
      for (size_t i=0; i<objects.size(); i++)
        if (objects[i]) objects[i]->clear();

      for (size_t i=0; i<builders.size(); i++)
	if (builders[i]) builders[i]->clear();

      refs.clear();
    }

    template<int N, typename Mesh>
    void BVHNBuilderTwoLevel<N,Mesh>::open_sequential(const size_t numPrimitives, const size_t maxOpenSize)
    {
      if (refs.size() == 0)
	return;

      size_t num = min(numPrimitives/400,maxOpenSize);
      refs.reserve(num);

#if 1
      for (size_t i=0;i<refs.size();i++)
      {
        NodeRef ref = refs[i].node;
        if (ref.isAlignedNode())
          ref.prefetch();
      }
#endif

      std::make_heap(refs.begin(),refs.end());
      while (refs.size()+3 <= num)
      {
        std::pop_heap (refs.begin(),refs.end());
        NodeRef ref = refs.back().node;
        if (ref.isLeaf()) break;
        refs.pop_back();

        AlignedNode* node = ref.alignedNode();
        for (size_t i=0; i<N; i++) {
          if (node->child(i) == BVH::emptyNode) continue;
          refs.push_back(BuildRef(node->bounds(i),node->child(i)));

#if 1
          NodeRef ref_pre = node->child(i);
          if (ref_pre.isAlignedNode())
            ref_pre.prefetch();
#endif
          std::push_heap (refs.begin(),refs.end());
        }
      }
    }

#if defined(EMBREE_GEOMETRY_LINES)
    Builder* BVH4BuilderTwoLevelLineSegmentsSAH (void* bvh, Scene* scene, const createLineSegmentsAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<4,LineSegments>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_TRIANGLES)
    Builder* BVH4BuilderTwoLevelTriangleMeshSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<4,TriangleMesh>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_QUADS)
    Builder* BVH4BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, const createQuadMeshAccelTy createMeshAccel) {
    return new BVHNBuilderTwoLevel<4,QuadMesh>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_USER)
    Builder* BVH4BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, const createAccelSetAccelTy createMeshAccel) {
    return new BVHNBuilderTwoLevel<4,AccelSet>((BVH4*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(__AVX__)
#if defined(EMBREE_GEOMETRY_TRIANGLES)
    Builder* BVH8BuilderTwoLevelTriangleMeshSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<8,TriangleMesh>((BVH8*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_QUADS)
    Builder* BVH8BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, const createQuadMeshAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<8,QuadMesh>((BVH8*)bvh,scene,createMeshAccel);
    }
#endif

#if defined(EMBREE_GEOMETRY_USER)
    Builder* BVH8BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, const createAccelSetAccelTy createMeshAccel) {
      return new BVHNBuilderTwoLevel<8,AccelSet>((BVH8*)bvh,scene,createMeshAccel);
    }
#endif
#endif
  }
}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#ifndef LIBREALSENSE_RS2_EXPORT_HPP
#define LIBREALSENSE_RS2_EXPORT_HPP

#include <map>
#include <fstream>
#include <cmath>
#include <string>
#include "rs_processing.hpp"

namespace rs2
{
    class save_to_ply : public filter
    {
    public:
        save_to_ply(std::string filename = "RealSense Pointcloud ", pointcloud pc = pointcloud())
            : filter([this](frame f, frame_source& s) { func(f, s); }),
            _pc(std::move(pc)), fname(filename)
        {
            register_simple_option(OPTION_IGNORE_COLOR, option_range{ 0, 1, 0, 1 });
        }

        DECLARE_PB_OPTION(OPTION_IGNORE_COLOR, 1);
    private:
        void func(frame data, frame_source& source)
        {
            frame depth, color;
            if (auto fs = data.as<frameset>()) {
                for (auto f : fs) {
                    if (f.is<points>()) depth = f;
                    else if (!depth && f.is<depth_frame>()) depth = f;
                    else if (!color && f.is<video_frame>()) color = f;
                }
            } else if (data.is<depth_frame>() || data.is<points>()) {
                depth = data;
            }

            if (!depth) throw std::runtime_error("Need depth data to save PLY");
            if (!depth.is<points>()) {
                if (color) _pc.map_to(color);
                depth = _pc.calculate(depth);
            }

            export_to_ply(depth, color);
            source.frame_ready(data); // passthrough filter because processing_block::process doesn't support sinks
        }

        void export_to_ply(points p, video_frame color) {
            const bool use_texcoords = color && get_option(OPTION_IGNORE_COLOR);
            const auto verts = p.get_vertices();
            const auto texcoords = p.get_texture_coordinates();
            std::vector<rs2::vertex> new_verts;
            std::vector<std::array<uint8_t, 3>> new_tex;
            std::map<int, int> idx_map;

            new_verts.reserve(p.size());
            if (use_texcoords) new_tex.reserve(p.size());

            static const auto min_distance = 1e-6;

            for (size_t i = 0; i < p.size(); ++i) {
                if (fabs(verts[i].x) >= min_distance || fabs(verts[i].y) >= min_distance ||
                    fabs(verts[i].z) >= min_distance)
                {
                    idx_map[i] = new_verts.size();
                    new_verts.push_back(verts[i]);
                    if (use_texcoords)
                    {
                        auto rgb = get_texcolor(color, texcoords[i].u, texcoords[i].v);
                        new_tex.push_back(rgb);
                    }
                }
            }

            auto profile = p.get_profile().as<video_stream_profile>();
            auto width = profile.width(), height = profile.height();
            static const auto threshold = 0.05f;
            std::vector<std::array<int, 3>> faces;
            for (int x = 0; x < width - 1; ++x) {
                for (int y = 0; y < height - 1; ++y) {
                    auto a = y * width + x, b = y * width + x + 1, c = (y + 1)*width + x, d = (y + 1)*width + x + 1;
                    if (verts[a].z && verts[b].z && verts[c].z && verts[d].z
                        && fabs(verts[a].z - verts[b].z) < threshold && fabs(verts[a].z - verts[c].z) < threshold
                        && fabs(verts[b].z - verts[d].z) < threshold && fabs(verts[c].z - verts[d].z) < threshold)
                    {
                        if (idx_map.count(a) == 0 || idx_map.count(b) == 0 || idx_map.count(c) == 0 ||
                            idx_map.count(d) == 0)
                            continue;
                        faces.push_back({ idx_map[a], idx_map[b], idx_map[d] });
                        faces.push_back({ idx_map[d], idx_map[c], idx_map[a] });
                    }
                }
            }

            std::ofstream out(fname + std::to_string(p.get_frame_number()) + ".ply");
            out << "ply\n";
            out << "format binary_little_endian 1.0\n" /*"format ascii 1.0\n"*/;
            out << "comment pointcloud saved from Realsense Viewer\n";
            out << "element vertex " << new_verts.size() << "\n";
            out << "property float" << sizeof(float) * 8 << " x\n";
            out << "property float" << sizeof(float) * 8 << " y\n";
            out << "property float" << sizeof(float) * 8 << " z\n";
            if (use_texcoords)
            {
                out << "property uchar red\n";
                out << "property uchar green\n";
                out << "property uchar blue\n";
            }
            out << "element face " << faces.size() << "\n";
            out << "property list uchar int vertex_indices\n";
            out << "end_header\n";
            out.close();

            out.open(fname + std::to_string(p.get_frame_number()) + ".ply", std::ios_base::app | std::ios_base::binary);
            for (int i = 0; i < new_verts.size(); ++i)
            {
                // we assume little endian architecture on your device
                out.write(reinterpret_cast<const char*>(&(new_verts[i].x)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].y)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].z)), sizeof(float));

                if (use_texcoords)
                {
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][0])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][1])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][2])), sizeof(uint8_t));
                }
            }
            auto size = faces.size();
            for (int i = 0; i < size; ++i) {
                static const int three = 3;
                out.write(reinterpret_cast<const char*>(&three), sizeof(uint8_t));
                out.write(reinterpret_cast<const char*>(&(faces[i][0])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][1])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][2])), sizeof(int));
            }
        }

        // TODO: get_texcolor, options API
        std::array<uint8_t, 3> get_texcolor(const video_frame& texture, float u, float v)
        {
            const int w = texture.get_width(), h = texture.get_height();
            int x = std::min(std::max(int(u*w + .5f), 0), w - 1);
            int y = std::min(std::max(int(v*h + .5f), 0), h - 1);
            int idx = x * texture.get_bytes_per_pixel() + y * texture.get_stride_in_bytes();
            const auto texture_data = reinterpret_cast<const uint8_t*>(texture.get_data());
            return { texture_data[idx], texture_data[idx + 1], texture_data[idx + 2] };
        }

        std::string fname;
        pointcloud _pc;
    };
}

#endif<commit_msg>Remove usage of std::to_string because it doesn't work on android<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#ifndef LIBREALSENSE_RS2_EXPORT_HPP
#define LIBREALSENSE_RS2_EXPORT_HPP

#include <map>
#include <fstream>
#include <cmath>
#include <sstream>
#include "rs_processing.hpp"

namespace rs2
{
    class save_to_ply : public filter
    {
    public:
        save_to_ply(std::string filename = "RealSense Pointcloud ", pointcloud pc = pointcloud())
            : filter([this](frame f, frame_source& s) { func(f, s); }),
            _pc(std::move(pc)), fname(filename)
        {
            register_simple_option(OPTION_IGNORE_COLOR, option_range{ 0, 1, 0, 1 });
        }

        DECLARE_PB_OPTION(OPTION_IGNORE_COLOR, 1);
    private:
        void func(frame data, frame_source& source)
        {
            frame depth, color;
            if (auto fs = data.as<frameset>()) {
                for (auto f : fs) {
                    if (f.is<points>()) depth = f;
                    else if (!depth && f.is<depth_frame>()) depth = f;
                    else if (!color && f.is<video_frame>()) color = f;
                }
            } else if (data.is<depth_frame>() || data.is<points>()) {
                depth = data;
            }

            if (!depth) throw std::runtime_error("Need depth data to save PLY");
            if (!depth.is<points>()) {
                if (color) _pc.map_to(color);
                depth = _pc.calculate(depth);
            }

            export_to_ply(depth, color);
            source.frame_ready(data); // passthrough filter because processing_block::process doesn't support sinks
        }

        void export_to_ply(points p, video_frame color) {
            const bool use_texcoords = color && get_option(OPTION_IGNORE_COLOR);
            const auto verts = p.get_vertices();
            const auto texcoords = p.get_texture_coordinates();
            std::vector<rs2::vertex> new_verts;
            std::vector<std::array<uint8_t, 3>> new_tex;
            std::map<int, int> idx_map;

            new_verts.reserve(p.size());
            if (use_texcoords) new_tex.reserve(p.size());

            static const auto min_distance = 1e-6;

            for (size_t i = 0; i < p.size(); ++i) {
                if (fabs(verts[i].x) >= min_distance || fabs(verts[i].y) >= min_distance ||
                    fabs(verts[i].z) >= min_distance)
                {
                    idx_map[i] = new_verts.size();
                    new_verts.push_back(verts[i]);
                    if (use_texcoords)
                    {
                        auto rgb = get_texcolor(color, texcoords[i].u, texcoords[i].v);
                        new_tex.push_back(rgb);
                    }
                }
            }

            auto profile = p.get_profile().as<video_stream_profile>();
            auto width = profile.width(), height = profile.height();
            static const auto threshold = 0.05f;
            std::vector<std::array<int, 3>> faces;
            for (int x = 0; x < width - 1; ++x) {
                for (int y = 0; y < height - 1; ++y) {
                    auto a = y * width + x, b = y * width + x + 1, c = (y + 1)*width + x, d = (y + 1)*width + x + 1;
                    if (verts[a].z && verts[b].z && verts[c].z && verts[d].z
                        && fabs(verts[a].z - verts[b].z) < threshold && fabs(verts[a].z - verts[c].z) < threshold
                        && fabs(verts[b].z - verts[d].z) < threshold && fabs(verts[c].z - verts[d].z) < threshold)
                    {
                        if (idx_map.count(a) == 0 || idx_map.count(b) == 0 || idx_map.count(c) == 0 ||
                            idx_map.count(d) == 0)
                            continue;
                        faces.push_back({ idx_map[a], idx_map[b], idx_map[d] });
                        faces.push_back({ idx_map[d], idx_map[c], idx_map[a] });
                    }
                }
            }

            std::stringstream name;
            name << fname << p.get_frame_number() << ".ply";
            std::ofstream out(name.str());
            out << "ply\n";
            out << "format binary_little_endian 1.0\n";
            out << "comment pointcloud saved from Realsense Viewer\n";
            out << "element vertex " << new_verts.size() << "\n";
            out << "property float" << sizeof(float) * 8 << " x\n";
            out << "property float" << sizeof(float) * 8 << " y\n";
            out << "property float" << sizeof(float) * 8 << " z\n";
            if (use_texcoords)
            {
                out << "property uchar red\n";
                out << "property uchar green\n";
                out << "property uchar blue\n";
            }
            out << "element face " << faces.size() << "\n";
            out << "property list uchar int vertex_indices\n";
            out << "end_header\n";
            out.close();

            out.open(name.str(), std::ios_base::app | std::ios_base::binary);
            for (int i = 0; i < new_verts.size(); ++i)
            {
                // we assume little endian architecture on your device
                out.write(reinterpret_cast<const char*>(&(new_verts[i].x)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].y)), sizeof(float));
                out.write(reinterpret_cast<const char*>(&(new_verts[i].z)), sizeof(float));

                if (use_texcoords)
                {
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][0])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][1])), sizeof(uint8_t));
                    out.write(reinterpret_cast<const char*>(&(new_tex[i][2])), sizeof(uint8_t));
                }
            }
            auto size = faces.size();
            for (int i = 0; i < size; ++i) {
                static const int three = 3;
                out.write(reinterpret_cast<const char*>(&three), sizeof(uint8_t));
                out.write(reinterpret_cast<const char*>(&(faces[i][0])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][1])), sizeof(int));
                out.write(reinterpret_cast<const char*>(&(faces[i][2])), sizeof(int));
            }
        }

        // TODO: get_texcolor, options API
        std::array<uint8_t, 3> get_texcolor(const video_frame& texture, float u, float v)
        {
            const int w = texture.get_width(), h = texture.get_height();
            int x = std::min(std::max(int(u*w + .5f), 0), w - 1);
            int y = std::min(std::max(int(v*h + .5f), 0), h - 1);
            int idx = x * texture.get_bytes_per_pixel() + y * texture.get_stride_in_bytes();
            const auto texture_data = reinterpret_cast<const uint8_t*>(texture.get_data());
            return { texture_data[idx], texture_data[idx + 1], texture_data[idx + 2] };
        }

        std::string fname;
        pointcloud _pc;
    };
}

#endif<|endoftext|>


<commit_before>/*

Copyright (c) 2010, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DISK_BUFFER_POOL_HPP
#define TORRENT_DISK_BUFFER_POOL_HPP

#include "libtorrent/config.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/session_settings.hpp"

#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
#include <boost/pool/pool.hpp>
#include "libtorrent/allocator.hpp"
#endif

namespace libtorrent
{

	struct TORRENT_EXPORT disk_buffer_pool : boost::noncopyable
	{
		disk_buffer_pool(int block_size);
#ifdef TORRENT_DEBUG
		~disk_buffer_pool();
#endif

#if defined TORRENT_DEBUG || defined TORRENT_DISK_STATS
		bool is_disk_buffer(char* buffer
			, mutex::scoped_lock& l) const;
		bool is_disk_buffer(char* buffer) const;
#endif

		char* allocate_buffer(char const* category);
		void free_buffer(char* buf);
		void free_multiple_buffers(char** bufvec, int numbufs);

		char* allocate_buffers(int blocks, char const* category);
		void free_buffers(char* buf, int blocks);

		int block_size() const { return m_block_size; }

#ifdef TORRENT_STATS
		int disk_allocations() const
		{ return m_allocations; }
#endif

#ifdef TORRENT_DISK_STATS
		std::ofstream m_disk_access_log;
#endif

		void release_memory();

		int in_use() const { return m_in_use; }

	protected:

		void free_buffer_impl(char* buf, mutex::scoped_lock& l);

		// number of bytes per block. The BitTorrent
		// protocol defines the block size to 16 KiB.
		const int m_block_size;

		// number of disk buffers currently allocated
		int m_in_use;

		session_settings m_settings;

	private:

		mutable mutex m_pool_mutex;

#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
		// memory pool for read and write operations
		// and disk cache
		boost::pool<page_aligned_allocator> m_pool;
#endif

#if defined TORRENT_DISK_STATS || defined TORRENT_STATS
		int m_allocations;
#endif
#ifdef TORRENT_DISK_STATS
	public:
		void rename_buffer(char* buf, char const* category);
	protected:
		std::map<std::string, int> m_categories;
		std::map<char*, std::string> m_buf_to_category;
		std::ofstream m_log;
	private:
#endif
#ifdef TORRENT_DEBUG
		int m_magic;
#endif
	};

}

#endif // TORRENT_DISK_BUFFER_POOL_HPP

<commit_msg>fixed some warnings<commit_after>/*

Copyright (c) 2010, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DISK_BUFFER_POOL_HPP
#define TORRENT_DISK_BUFFER_POOL_HPP

#include "libtorrent/config.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/session_settings.hpp"

#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
#include <boost/pool/pool.hpp>
#include "libtorrent/allocator.hpp"
#endif

namespace libtorrent
{

	struct TORRENT_EXPORT disk_buffer_pool : boost::noncopyable
	{
		disk_buffer_pool(int block_size);
#ifdef TORRENT_DEBUG
		~disk_buffer_pool();
#endif

#if defined TORRENT_DEBUG || defined TORRENT_DISK_STATS
		bool is_disk_buffer(char* buffer
			, mutex::scoped_lock& l) const;
		bool is_disk_buffer(char* buffer) const;
#endif

		char* allocate_buffer(char const* category);
		void free_buffer(char* buf);
		void free_multiple_buffers(char** bufvec, int numbufs);

		char* allocate_buffers(int blocks, char const* category);
		void free_buffers(char* buf, int blocks);

		int block_size() const { return m_block_size; }

#ifdef TORRENT_STATS
		int disk_allocations() const
		{ return m_allocations; }
#endif

#ifdef TORRENT_DISK_STATS
		std::ofstream m_disk_access_log;
#endif

		void release_memory();

		boost::uint32_t in_use() const { return m_in_use; }

	protected:

		void free_buffer_impl(char* buf, mutex::scoped_lock& l);

		// number of bytes per block. The BitTorrent
		// protocol defines the block size to 16 KiB.
		const int m_block_size;

		// number of disk buffers currently allocated
		boost::uint32_t m_in_use;

		session_settings m_settings;

	private:

		mutable mutex m_pool_mutex;

#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
		// memory pool for read and write operations
		// and disk cache
		boost::pool<page_aligned_allocator> m_pool;
#endif

#if defined TORRENT_DISK_STATS || defined TORRENT_STATS
		int m_allocations;
#endif
#ifdef TORRENT_DISK_STATS
	public:
		void rename_buffer(char* buf, char const* category);
	protected:
		std::map<std::string, int> m_categories;
		std::map<char*, std::string> m_buf_to_category;
		std::ofstream m_log;
	private:
#endif
#ifdef TORRENT_DEBUG
		int m_magic;
#endif
	};

}

#endif // TORRENT_DISK_BUFFER_POOL_HPP

<|endoftext|>


<commit_before>#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <time.h>
#include <unistd.h>

#include "objectTracking/ColorTracker.h"
#include "objectTracking/Flooder.h"

cv::VideoCapture camera(0);

Vec3 targetColor(29, 227, 218);
Vec3 minColor;
Vec3 maxColor;
Vec3 redColor(1, 227, 218);
Vec3 minRed;
Vec3 maxRed;

Vec3 threshold(20, 100, 100);

bool running = true;

//Used as a safe way of shutting down the program since ctrl+c doesn't stop
//using the webcam
void onMouse(int event, int x, int y, int, void*);
void selectColor(int event, int x, int y, int , void*);
void setMinMaxColor(Vec3 target, Vec3* minColor, Vec3* maxColor, Vec3 threshold);

int main()
{

    if(camera.isOpened() == false)
    {
        std::cout << "Failed to open camera" << std::endl;
    }

    //capture 1 image for use as reference
    cv::Mat ref;
    camera >> ref;

    ColorTracker ct;
    ct.setImage(ref);

    //targetColor = ct.getObjectColor();
    minColor = targetColor - threshold;
    maxColor = targetColor + threshold;
    minRed = redColor - threshold;
    maxRed = redColor + threshold;

    cv::namedWindow("GUI");
    cv::setMouseCallback("GUI", onMouse);

    cv::namedWindow("Display Image");
    cv::setMouseCallback("Display Image", selectColor);

    cv::namedWindow("Threshold img");
    cv::moveWindow("Threshold img", 0, 0);
    //cv::namedWindow("red img");
    //cv::moveWindow("red img", 50, 450);
    //usleep(1000);

    while(running == true)
    {
        cv::Mat img;
        camera >> img;

        clock_t startTime = clock();

        //Colortracking
        ColorTracker ct;
        ct.setImage(img);
        ct.generateBinary(minColor, maxColor, true);

        //ColorTracker rt;
        //rt.setImage(img);
        //rt.generateBinary(minRed, maxRed, true);

        //Getting the blob data from the trackers
        ct.generateBlobs();
        std::deque< Flooder::Blob > blobs = ct.getBlobs(250);

        int maxBlobSize = 0;
        for(unsigned int i = 0; i < blobs.size(); i++)
        {
            if(blobs.at(i).pixelAmount > maxBlobSize)
            {
                maxBlobSize = blobs.at(i).pixelAmount;
            }
        }
        std::cout << "The biggset blob is: " << maxBlobSize << std::endl;

        for(unsigned int i = 0; i < blobs.size(); i++)
        {
            ct.drawCircle(blobs.at(i).center, 10, cv::Scalar(255, 0, 0));
        }

        clock_t endTime = clock();

        std::cout << "Search took: " << (float)(endTime-startTime)/CLOCKS_PER_SEC << std::endl;
        std::cout << "Found: " << blobs.size() << " blobs" << std::endl;

        cv::imshow("Threshold img", ct.getBinary());
        cv::imshow("Display Image", img);

        cv::waitKey(10);
    }

    return 0;
}

void onMouse(int event, int x, int y, int, void*)
{
    if(event != 1)
    {
        return;
    }

    //Exiting the program
    running = false;
}

void selectColor(int event, int x, int y, int, void*)
{
    if(event != 1) //If this isn't a left click
    {
        return;
    }

    //Taking 1 image
    cv::Mat ref;
    camera >> ref;

    //Create a color tracker to get the color
    ColorTracker ct;
    ct.setImage(ref);

    redColor = ct.getColorInPixel(Vec2(x, y));

    //Recalculating the threshold
    setMinMaxColor(redColor, &minRed, &maxRed, threshold);
}

void setMinMaxColor(Vec3 target, Vec3* minColor, Vec3* maxColor, Vec3 threshold)
{
    *minColor = target - threshold;
    *maxColor = target + threshold;
}
<commit_msg>fix stupid code<commit_after>#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <time.h>
#include <unistd.h>

#include "objectTracking/ColorTracker.h"
#include "objectTracking/Flooder.h"

cv::VideoCapture camera(0);

Vec3 targetColor(29, 227, 218);
Vec3 minColor;
Vec3 maxColor;
Vec3 redColor(1, 227, 218);
Vec3 minRed;
Vec3 maxRed;

Vec3 threshold(20, 100, 100);

bool running = true;

//Used as a safe way of shutting down the program since ctrl+c doesn't stop
//using the webcam
void onMouse(int event, int x, int y, int, void*);
void selectColor(int event, int x, int y, int , void*);
void setMinMaxColor(Vec3 target, Vec3& minColor, Vec3& maxColor, Vec3 threshold);

int main()
{

    if(camera.isOpened() == false)
    {
        std::cout << "Failed to open camera" << std::endl;
    }

    //capture 1 image for use as reference
    cv::Mat ref;
    camera >> ref;

    ColorTracker ct;
    ct.setImage(ref);

    //targetColor = ct.getObjectColor();
    minColor = targetColor - threshold;
    maxColor = targetColor + threshold;
    minRed = redColor - threshold;
    maxRed = redColor + threshold;

    cv::namedWindow("GUI");
    cv::setMouseCallback("GUI", onMouse);

    cv::namedWindow("Display Image");
    cv::setMouseCallback("Display Image", selectColor);

    cv::namedWindow("Threshold img");
    cv::moveWindow("Threshold img", 0, 0);
    //cv::namedWindow("red img");
    //cv::moveWindow("red img", 50, 450);
    //usleep(1000);

    while(running == true)
    {
        cv::Mat img;
        camera >> img;

        clock_t startTime = clock();

        //Colortracking
        ColorTracker ct;
        ct.setImage(img);
        ct.generateBinary(minColor, maxColor, true);

        //ColorTracker rt;
        //rt.setImage(img);
        //rt.generateBinary(minRed, maxRed, true);

        //Getting the blob data from the trackers
        ct.generateBlobs();
        std::deque< Flooder::Blob > blobs = ct.getBlobs(250);

        int maxBlobSize = 0;
        for(unsigned int i = 0; i < blobs.size(); i++)
        {
            if(blobs.at(i).pixelAmount > maxBlobSize)
            {
                maxBlobSize = blobs.at(i).pixelAmount;
            }
        }
        std::cout << "The biggset blob is: " << maxBlobSize << std::endl;

        for(unsigned int i = 0; i < blobs.size(); i++)
        {
            ct.drawCircle(blobs.at(i).center, 10, cv::Scalar(255, 0, 0));
        }

        clock_t endTime = clock();

        std::cout << "Search took: " << (float)(endTime-startTime)/CLOCKS_PER_SEC << std::endl;
        std::cout << "Found: " << blobs.size() << " blobs" << std::endl;

        cv::imshow("Threshold img", ct.getBinary());
        cv::imshow("Display Image", img);

        cv::waitKey(10);
    }

    return 0;
}

void onMouse(int event, int x, int y, int, void*)
{
    if(event != 1)
    {
        return;
    }

    //Exiting the program
    running = false;
}

void selectColor(int event, int x, int y, int, void*)
{
    if(event != 1) //If this isn't a left click
    {
        return;
    }

    //Taking 1 image
    cv::Mat ref;
    camera >> ref;

    //Create a color tracker to get the color
    ColorTracker ct;
    ct.setImage(ref);

    redColor = ct.getColorInPixel(Vec2(x, y));

    //Recalculating the threshold
    setMinMaxColor(redColor, minColor, maxColor, threshold);
}

void setMinMaxColor(Vec3 target, Vec3& minColor, Vec3& maxColor, Vec3 threshold)
{
    minColor = target - threshold;
    maxColor = target + threshold;
}
<|endoftext|>