<commit_before>#include "catch.hpp"

#include "base/rect.h"

TEST_CASE("rect-test", "[rect]")
{
    // rect at x,y  w,h
    /*
      (1,6)      (4,6)
        -----------
        |         |
        |         | h=4
        |   w=3   |
        -----------
      (1,2)       (4, 2)
    */
    auto r = recti{1, 2, 3, 4};
    CHECK(r.x == 1);
    CHECK(r.y == 2);
    CHECK(r.width == 3);
    CHECK(r.height == 4);

    CHECK(r.get_left() == 1);
    CHECK(r.get_right() == 4);
    CHECK(r.get_bottom() == 2);
    CHECK(r.get_top() == 6);

    ///////////////////////////////////////////////////////////////////////////
    // set_foobar(...)

    SECTION("set top")
    {
        r.set_top(42);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 42);
    }

    SECTION("set left")
    {
        r.set_left(-42);
        CHECK(r.get_left() == -42);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("set right")
    {
        r.set_right(42);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 42);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("set bottom")
    {
        r.set_bottom(-42);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == -42);
        CHECK(r.get_top() == 6);
    }

    ///////////////////////////////////////////////////////////////////////////
    // cut

    SECTION("cut left")
    {
        const auto cut = r.cut_left(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 2);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 2);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("cut right")
    {
        const auto cut = r.cut_right(1);
        CHECK(cut.get_left() == 3);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 3);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("cut top")
    {
        const auto cut = r.cut_top(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 5);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 5);
    }

    SECTION("cut bottom")
    {
        const auto cut = r.cut_bottom(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 3);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 3);
        CHECK(r.get_top() == 6);
    }

    ///////////////////////////////////////////////////////////////////////////
    // get_cut
    SECTION("get cut left")
    {
        const auto cut = r.get_cut_left(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 2);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("get cut right")
    {
        const auto cut = r.get_cut_right(1);
        CHECK(cut.get_left() == 3);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("get cut top")
    {
        const auto cut = r.get_cut_top(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 5);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("get cut bottom")
    {
        const auto cut = r.get_cut_bottom(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 3);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    ///////////////////////////////////////////////////////////////////////////
    // get_offset

    ///////////////////////////////////////////////////////////////////////////
    // get_inset

    SECTION("inset 1")
    {
        const auto rr = r.get_inset(1);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);

        CHECK(rr.get_left() == 2);
        CHECK(rr.get_right() == 3);
        CHECK(rr.get_bottom() == 3);
        CHECK(rr.get_top() == 5);
    }

    SECTION("inset -1")
    {
        const auto rr = r.get_inset(-1);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);

        CHECK(rr.get_left() == 0);
        CHECK(rr.get_right() == 5);
        CHECK(rr.get_bottom() == 1);
        CHECK(rr.get_top() == 7);
    }
}

<commit_msg>test: rect test completed<commit_after>#include "catch.hpp"

#include "base/rect.h"

TEST_CASE("rect-test", "[rect]")
{
    // rect at x,y  w,h
    /*
      (1,6)      (4,6)
        -----------
        |         |
        |         | h=4
        |   w=3   |
        -----------
      (1,2)       (4, 2)
    */
    auto r = recti{1, 2, 3, 4};
    CHECK(r.x == 1);
    CHECK(r.y == 2);
    CHECK(r.width == 3);
    CHECK(r.height == 4);

    CHECK(r.get_left() == 1);
    CHECK(r.get_right() == 4);
    CHECK(r.get_bottom() == 2);
    CHECK(r.get_top() == 6);

    ///////////////////////////////////////////////////////////////////////////
    // set_foobar(...)

    SECTION("set top")
    {
        r.set_top(42);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 42);
    }

    SECTION("set left")
    {
        r.set_left(-42);
        CHECK(r.get_left() == -42);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("set right")
    {
        r.set_right(42);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 42);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("set bottom")
    {
        r.set_bottom(-42);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == -42);
        CHECK(r.get_top() == 6);
    }

    ///////////////////////////////////////////////////////////////////////////
    // cut

    SECTION("cut left")
    {
        const auto cut = r.cut_left(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 2);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 2);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("cut right")
    {
        const auto cut = r.cut_right(1);
        CHECK(cut.get_left() == 3);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 3);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("cut top")
    {
        const auto cut = r.cut_top(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 5);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 5);
    }

    SECTION("cut bottom")
    {
        const auto cut = r.cut_bottom(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 3);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 3);
        CHECK(r.get_top() == 6);
    }

    ///////////////////////////////////////////////////////////////////////////
    // get_cut
    SECTION("get cut left")
    {
        const auto cut = r.get_cut_left(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 2);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("get cut right")
    {
        const auto cut = r.get_cut_right(1);
        CHECK(cut.get_left() == 3);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("get cut top")
    {
        const auto cut = r.get_cut_top(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 5);
        CHECK(cut.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("get cut bottom")
    {
        const auto cut = r.get_cut_bottom(1);
        CHECK(cut.get_left() == 1);
        CHECK(cut.get_right() == 4);
        CHECK(cut.get_bottom() == 2);
        CHECK(cut.get_top() == 3);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    ///////////////////////////////////////////////////////////////////////////
    // get_offset

    SECTION("get offset (0,0)")
    {
        const auto off = r.get_offset({0, 0});
        CHECK(off.get_left() == 1);
        CHECK(off.get_right() == 4);
        CHECK(off.get_bottom() == 2);
        CHECK(off.get_top() == 6);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    SECTION("get offset (...)")
    {
        const auto off = r.get_offset({1, 2});
        CHECK(off.get_left() == 2);
        CHECK(off.get_right() == 5);
        CHECK(off.get_bottom() == 4);
        CHECK(off.get_top() == 8);

        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);
    }

    ///////////////////////////////////////////////////////////////////////////
    // get_inset

    SECTION("inset 1")
    {
        const auto rr = r.get_inset(1);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);

        CHECK(rr.get_left() == 2);
        CHECK(rr.get_right() == 3);
        CHECK(rr.get_bottom() == 3);
        CHECK(rr.get_top() == 5);
    }

    SECTION("inset -1")
    {
        const auto rr = r.get_inset(-1);
        CHECK(r.get_left() == 1);
        CHECK(r.get_right() == 4);
        CHECK(r.get_bottom() == 2);
        CHECK(r.get_top() == 6);

        CHECK(rr.get_left() == 0);
        CHECK(rr.get_right() == 5);
        CHECK(rr.get_bottom() == 1);
        CHECK(rr.get_top() == 7);
    }
}

<|endoftext|>


<commit_before>//
// Created by Rui Wang on 16-4-30.
//

#include "gtest/gtest.h"
#include "harness.h"

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <backend/planner/hybrid_scan_plan.h>
#include <backend/executor/hybrid_scan_executor.h>

#include "backend/catalog/manager.h"
#include "backend/catalog/schema.h"
#include "backend/concurrency/transaction.h"
#include "backend/concurrency/transaction_manager_factory.h"
#include "backend/common/timer.h"
#include "backend/executor/abstract_executor.h"
#include "backend/executor/insert_executor.h"
#include "backend/index/index_factory.h"
#include "backend/planner/insert_plan.h"
#include "backend/storage/tile.h"
#include "backend/storage/tile_group.h"
#include "backend/storage/data_table.h"
#include "backend/storage/table_factory.h"
#include "backend/expression/expression_util.h"
#include "backend/expression/abstract_expression.h"
#include "backend/expression/constant_value_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/comparison_expression.h"
#include "backend/expression/conjunction_expression.h"

#include "backend/index/index_factory.h"

namespace peloton {
namespace test {

class HybridIndexTests : public PelotonTest {};

static double projectivity = 1.0;
static int columncount = 4;
static size_t tuples_per_tile_group = 10;
static size_t tile_group = 10;

void CreateTable(std::unique_ptr<storage::DataTable>& hyadapt_table, bool indexes) {
  oid_t column_count = projectivity * columncount;

  const oid_t col_count = column_count + 1;
  const bool is_inlined = true;

  // Create schema first
  std::vector<catalog::Column> columns;

  for (oid_t col_itr = 0; col_itr < col_count; col_itr++) {
    auto column =
      catalog::Column(VALUE_TYPE_INTEGER, GetTypeSize(VALUE_TYPE_INTEGER),
                      "" + std::to_string(col_itr), is_inlined);

    columns.push_back(column);
  }

  catalog::Schema *table_schema = new catalog::Schema(columns);
  std::string table_name("HYADAPTTABLE");

  /////////////////////////////////////////////////////////
  // Create table.
  /////////////////////////////////////////////////////////

  bool own_schema = true;
  bool adapt_table = true;
  hyadapt_table.reset(storage::TableFactory::GetDataTable(
    INVALID_OID, INVALID_OID, table_schema, table_name,
    tuples_per_tile_group, own_schema, adapt_table));

  // PRIMARY INDEX
  if (indexes == true) {
    std::vector<oid_t> key_attrs;

    auto tuple_schema = hyadapt_table->GetSchema();
    catalog::Schema *key_schema;
    index::IndexMetadata *index_metadata;
    bool unique;

    key_attrs = {0};
    key_schema = catalog::Schema::CopySchema(tuple_schema, key_attrs);
    key_schema->SetIndexedColumns(key_attrs);

    unique = true;

    index_metadata = new index::IndexMetadata(
      "primary_index", 123, INDEX_TYPE_BTREE,
      INDEX_CONSTRAINT_TYPE_PRIMARY_KEY, tuple_schema, key_schema, unique);

    index::Index *pkey_index = index::IndexFactory::GetInstance(index_metadata);
    hyadapt_table->AddIndex(pkey_index);
  }
}

void LoadTable(std::unique_ptr<storage::DataTable>& hyadapt_table) {
  oid_t column_count = projectivity * columncount;
  const oid_t col_count = column_count + 1;
  const int tuple_count = tile_group * tuples_per_tile_group;

  auto table_schema = hyadapt_table->GetSchema();

  /////////////////////////////////////////////////////////
  // Load in the data
  /////////////////////////////////////////////////////////

  // Insert tuples into tile_group.
  //auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  const bool allocate = true;
  //auto txn = txn_manager.BeginTransaction();
  std::unique_ptr<VarlenPool> pool(new VarlenPool(BACKEND_TYPE_MM));

  int rowid;
  for (rowid = 0; rowid < tuple_count; rowid++) {
    int populate_value = rowid;

    storage::Tuple tuple(table_schema, allocate);

    for (oid_t col_itr = 0; col_itr < col_count; col_itr++) {
      auto value = ValueFactory::GetIntegerValue(populate_value);
      tuple.SetValue(col_itr, value, pool.get());
    }

    ItemPointer tuple_slot_id = hyadapt_table->InsertTuple(&tuple);
    assert(tuple_slot_id.block != INVALID_OID);
    assert(tuple_slot_id.offset != INVALID_OID);
    //txn->RecordInsert(tuple_slot_id);
  }

  //txn_manager.CommitTransaction();
}

expression::AbstractExpression *CreatePredicate(const int lower_bound) {
  // ATTR0 >= LOWER_BOUND

  // First, create tuple value expression.
  expression::AbstractExpression *tuple_value_expr =
    expression::ExpressionUtil::TupleValueFactory(0, 0);

  // Second, create constant value expression.
  Value constant_value = ValueFactory::GetIntegerValue(lower_bound);

  expression::AbstractExpression *constant_value_expr =
    expression::ExpressionUtil::ConstantValueFactory(constant_value);

  // Finally, link them together using an greater than expression.
  expression::AbstractExpression *predicate =
    expression::ExpressionUtil::ComparisonFactory(
      EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO, tuple_value_expr,
      constant_value_expr);

  return predicate;
}

void GenerateSequence(std::vector<oid_t>& hyadapt_column_ids, oid_t column_count) {
  // Reset sequence
  hyadapt_column_ids.clear();

  // Generate sequence
  for (oid_t column_id = 1; column_id <= column_count; column_id++)
    hyadapt_column_ids.push_back(column_id);

  std::random_shuffle(hyadapt_column_ids.begin(), hyadapt_column_ids.end());
}

void ExecuteTest(executor::AbstractExecutor *executor, size_t tiple_group_counts) {
  Timer<> timer;

  size_t tuple_counts = 0;
  timer.Start();
  bool status = false;

  status = executor->Init();
  if (status == false) throw Exception("Init failed");

  std::vector<std::unique_ptr<executor::LogicalTile>> result_tiles;

  while (executor->Execute() == true) {
      std::unique_ptr<executor::LogicalTile> result_tile(
        executor->GetOutput());
      tuple_counts += result_tile->GetTupleCount();
      result_tiles.emplace_back(result_tile.release());
      tiple_group_counts--;
  }

  // Execute stuff
  executor->Execute();

  timer.Stop();
  double time_per_transaction = timer.GetDuration();
  LOG_INFO("%f", time_per_transaction);
  EXPECT_EQ(tiple_group_counts, 0);
  EXPECT_EQ(tuple_counts, tile_group * tuples_per_tile_group);
}

TEST_F(HybridIndexTests, SeqScanTest) {
  std::unique_ptr<storage::DataTable> hyadapt_table;
  CreateTable(hyadapt_table, false);
  //LoadTable(hyadapt_table);

  LOG_INFO("%s", hyadapt_table->GetInfo().c_str());

  const int lower_bound = 30;
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  auto txn = txn_manager.BeginTransaction();

  /////////////////////////////////////////////////////////
  // SEQ SCAN + PREDICATE
  /////////////////////////////////////////////////////////

  std::unique_ptr<executor::ExecutorContext> context(
  new executor::ExecutorContext(txn));

  // Column ids to be added to logical tile after scan.
  std::vector<oid_t> column_ids;
//  oid_t column_count = state.projectivity * state.column_count;
  oid_t column_count = projectivity * columncount;
  std::vector<oid_t> hyadapt_column_ids;

  GenerateSequence(hyadapt_column_ids, column_count);

  for (oid_t col_itr = 0; col_itr < column_count; col_itr++) {
    column_ids.push_back(hyadapt_column_ids[col_itr]);
  }

  // Create and set up seq scan executor
  auto predicate = nullptr; // CreatePredicate(lower_bound);
  planner::HybridScanPlan hybrid_scan_node(hyadapt_table.get(), predicate, column_ids);

  executor::HybridScanExecutor Hybrid_scan_executor(&hybrid_scan_node, context.get());

  ExecuteTest(&Hybrid_scan_executor, hyadapt_table->hyGetTileGroupCount());

  txn_manager.CommitTransaction();
}

}  // namespace tet
}  // namespace peloton
<commit_msg>update<commit_after>//
// Created by Rui Wang on 16-4-30.
//

#include "gtest/gtest.h"
#include "harness.h"

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <backend/planner/hybrid_scan_plan.h>
#include <backend/executor/hybrid_scan_executor.h>

#include "backend/catalog/manager.h"
#include "backend/catalog/schema.h"
#include "backend/concurrency/transaction.h"
#include "backend/concurrency/transaction_manager_factory.h"
#include "backend/common/timer.h"
#include "backend/executor/abstract_executor.h"
#include "backend/executor/insert_executor.h"
#include "backend/index/index_factory.h"
#include "backend/planner/insert_plan.h"
#include "backend/storage/tile.h"
#include "backend/storage/tile_group.h"
#include "backend/storage/data_table.h"
#include "backend/storage/table_factory.h"
#include "backend/expression/expression_util.h"
#include "backend/expression/abstract_expression.h"
#include "backend/expression/constant_value_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/comparison_expression.h"
#include "backend/expression/conjunction_expression.h"

#include "backend/index/index_factory.h"

namespace peloton {
namespace test {

class HybridIndexTests : public PelotonTest {};

static double projectivity = 1.0;
static int columncount = 4;
static size_t tuples_per_tile_group = 10;
static size_t tile_group = 10;

void CreateTable(std::unique_ptr<storage::DataTable>& hyadapt_table, bool indexes) {
  oid_t column_count = projectivity * columncount;

  const oid_t col_count = column_count + 1;
  const bool is_inlined = true;

  // Create schema first
  std::vector<catalog::Column> columns;

  for (oid_t col_itr = 0; col_itr < col_count; col_itr++) {
    auto column =
      catalog::Column(VALUE_TYPE_INTEGER, GetTypeSize(VALUE_TYPE_INTEGER),
                      "" + std::to_string(col_itr), is_inlined);

    columns.push_back(column);
  }

  catalog::Schema *table_schema = new catalog::Schema(columns);
  std::string table_name("HYADAPTTABLE");

  /////////////////////////////////////////////////////////
  // Create table.
  /////////////////////////////////////////////////////////

  bool own_schema = true;
  bool adapt_table = true;
  hyadapt_table.reset(storage::TableFactory::GetDataTable(
    INVALID_OID, INVALID_OID, table_schema, table_name,
    tuples_per_tile_group, own_schema, adapt_table));

  // PRIMARY INDEX
  if (indexes == true) {
    std::vector<oid_t> key_attrs;

    auto tuple_schema = hyadapt_table->GetSchema();
    catalog::Schema *key_schema;
    index::IndexMetadata *index_metadata;
    bool unique;

    key_attrs = {0};
    key_schema = catalog::Schema::CopySchema(tuple_schema, key_attrs);
    key_schema->SetIndexedColumns(key_attrs);

    unique = true;

    index_metadata = new index::IndexMetadata(
      "primary_index", 123, INDEX_TYPE_BTREE,
      INDEX_CONSTRAINT_TYPE_PRIMARY_KEY, tuple_schema, key_schema, unique);

    index::Index *pkey_index = index::IndexFactory::GetInstance(index_metadata);
    hyadapt_table->AddIndex(pkey_index);
  }
}

void LoadTable(std::unique_ptr<storage::DataTable>& hyadapt_table) {
  oid_t column_count = projectivity * columncount;
  const oid_t col_count = column_count + 1;
  const int tuple_count = tile_group * tuples_per_tile_group;

  auto table_schema = hyadapt_table->GetSchema();

  /////////////////////////////////////////////////////////
  // Load in the data
  /////////////////////////////////////////////////////////

  // Insert tuples into tile_group.
  //auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  const bool allocate = true;
  //auto txn = txn_manager.BeginTransaction();
  std::unique_ptr<VarlenPool> pool(new VarlenPool(BACKEND_TYPE_MM));

  int rowid;
  for (rowid = 0; rowid < tuple_count; rowid++) {
    int populate_value = rowid;

    storage::Tuple tuple(table_schema, allocate);

    for (oid_t col_itr = 0; col_itr < col_count; col_itr++) {
      auto value = ValueFactory::GetIntegerValue(populate_value);
      tuple.SetValue(col_itr, value, pool.get());
    }

    ItemPointer tuple_slot_id = hyadapt_table->InsertTuple(&tuple);
    assert(tuple_slot_id.block != INVALID_OID);
    assert(tuple_slot_id.offset != INVALID_OID);
    //txn->RecordInsert(tuple_slot_id);
  }

  //txn_manager.CommitTransaction();
}

expression::AbstractExpression *CreatePredicate(const int lower_bound) {
  // ATTR0 >= LOWER_BOUND

  // First, create tuple value expression.
  expression::AbstractExpression *tuple_value_expr =
    expression::ExpressionUtil::TupleValueFactory(0, 0);

  // Second, create constant value expression.
  Value constant_value = ValueFactory::GetIntegerValue(lower_bound);

  expression::AbstractExpression *constant_value_expr =
    expression::ExpressionUtil::ConstantValueFactory(constant_value);

  // Finally, link them together using an greater than expression.
  expression::AbstractExpression *predicate =
    expression::ExpressionUtil::ComparisonFactory(
      EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO, tuple_value_expr,
      constant_value_expr);

  return predicate;
}

void GenerateSequence(std::vector<oid_t>& hyadapt_column_ids, oid_t column_count) {
  // Reset sequence
  hyadapt_column_ids.clear();

  // Generate sequence
  for (oid_t column_id = 0; column_id < column_count; column_id++)
    hyadapt_column_ids.push_back(column_id);

  // std::random_shuffle(hyadapt_column_ids.begin(), hyadapt_column_ids.end());
}

void ExecuteTest(executor::AbstractExecutor *executor, size_t tiple_group_counts) {
  Timer<> timer;

  size_t tuple_counts = 0;
  timer.Start();
  bool status = false;

  status = executor->Init();
  if (status == false) throw Exception("Init failed");

  std::vector<std::unique_ptr<executor::LogicalTile>> result_tiles;

  while (executor->Execute() == true) {
      std::unique_ptr<executor::LogicalTile> result_tile(
        executor->GetOutput());
      tuple_counts += result_tile->GetTupleCount();
      result_tiles.emplace_back(result_tile.release());
      tiple_group_counts--;
  }

  // Execute stuff
  executor->Execute();

  timer.Stop();
  double time_per_transaction = timer.GetDuration();
  LOG_INFO("%f", time_per_transaction);
  EXPECT_EQ(tiple_group_counts, 0);
  EXPECT_EQ(tuple_counts, tile_group * tuples_per_tile_group);
}

TEST_F(HybridIndexTests, SeqScanTest) {
  std::unique_ptr<storage::DataTable> hyadapt_table;
  CreateTable(hyadapt_table, false);
  //LoadTable(hyadapt_table);

  LOG_INFO("%s", hyadapt_table->GetInfo().c_str());

  const int lower_bound = 30;
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  auto txn = txn_manager.BeginTransaction();

  /////////////////////////////////////////////////////////
  // SEQ SCAN + PREDICATE
  /////////////////////////////////////////////////////////

  std::unique_ptr<executor::ExecutorContext> context(
  new executor::ExecutorContext(txn));

  // Column ids to be added to logical tile after scan.
  std::vector<oid_t> column_ids;
//  oid_t column_count = state.projectivity * state.column_count;
  oid_t column_count = projectivity * columncount;
  std::vector<oid_t> hyadapt_column_ids;

  GenerateSequence(hyadapt_column_ids, column_count);

  for (oid_t col_itr = 0; col_itr < column_count; col_itr++) {
    column_ids.push_back(hyadapt_column_ids[col_itr]);
  }

  // Create and set up seq scan executor
  auto predicate = nullptr; // CreatePredicate(lower_bound);
  planner::HybridScanPlan hybrid_scan_node(hyadapt_table.get(), predicate, column_ids);

  executor::HybridScanExecutor Hybrid_scan_executor(&hybrid_scan_node, context.get());

  ExecuteTest(&Hybrid_scan_executor, hyadapt_table->hyGetTileGroupCount());

  txn_manager.CommitTransaction();
}

}  // namespace tet
}  // namespace peloton
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#pragma once

#include <string>

#include <gui/types.hpp>

namespace gui {
	struct image_ref;
	struct node;
	struct style_save { int __unused; };
	using style_handle = style_save*;

	struct point {
		pixels x;
		pixels y;

		point() : x(0), y(0) {}
		point(const pixels& x, const pixels& y) : x(x), y(y) {}
		point(const point&) = default;
		point& operator=(const point&) = default;
		point(point&&) = default;
		point& operator=(point&&) = default;
	};

	struct size {
		pixels width;
		pixels height;

		size() : width(0), height(0) {}
		size(const pixels& width, const pixels& height) : width(width), height(height) {}
		size(const size&) = default;
		size& operator=(const size&) = default;
		size(size&&) = default;
		size& operator=(size&&) = default;

		bool empty() const
		{
			return !width.value() || !height.value();
		}
	};

	inline point operator + (const point& lhs, const point& rhs) {
		return{ lhs.x + rhs.x, lhs.y + rhs.y };
	}

	inline point operator + (const point& lhs, const size& rhs) {
		return{ lhs.x + rhs.width, lhs.y + rhs.height };
	}

	inline size operator - (const point& lhs, const point& rhs) {
		return{ std::abs((lhs.x - rhs.x).value()), std::abs((lhs.y - rhs.y).value()) };
	}

	struct rect {
		gui::point origin;
		gui::size size;

		rect() = default;
		rect(const gui::point& topleft, const gui::point& bottomright) : origin(topleft), size(bottomright - topleft) {}
		rect(const gui::point& origin, const gui::size& size) : origin(origin), size(size) {}
		rect(const rect&) = default;
		rect& operator=(const rect&) = default;
		rect(rect&&) = default;
		rect& operator=(rect&&) = default;
	};

	struct ratio {
		int num;
		int denom;

		long double scaleD(const pixels& px) const
		{
			return num * px.value() / denom;
		}

		float scaleF(const pixels& px) const
		{
			return (float)(num * px.value() / denom);
		}

		long scaleL(const pixels& px) const
		{
			return (long)(0.5 + num * px.value() / denom);
		}

		int scaleI(const pixels& px) const
		{
			return (int)(0.5 + num * px.value() / denom);
		}

		pixels invert(int value) const {
			return (long double)value * denom / num;
		}

		pixels invert(double value) const {
			return (long double)value * denom / num;
		}

		pixels invert(long double value) const {
			return value * denom / num;
		}

		static int GCD(int a, int b) {
			if (!b)
				return a;

			return GCD(b, a % b);
		}

		ratio gcd() const {
			auto factor = GCD(num, denom);
			return{ num / factor, denom / factor };
		}
	};

	inline ratio operator * (const ratio& lhs, const ratio& rhs)
	{
		auto out = lhs.gcd();
		auto right = rhs.gcd();

		auto gcd = ratio::GCD(out.num, right.denom);
		out.num /= gcd;
		right.denom /= gcd;

		gcd = ratio::GCD(right.num, out.denom);
		right.num /= gcd;
		out.denom /= gcd;

		out.num *= right.num;
		out.denom *= right.denom;

		return out;
	}

	struct painter {
		virtual ~painter() {}
		virtual void moveOrigin(const pixels& x, const pixels& y) = 0;
		void moveOrigin(const point& pt) { moveOrigin(pt.x, pt.y); }
		virtual point getOrigin() const = 0;
		virtual void setOrigin(const point& orig) = 0;
		virtual void paintImage(const image_ref* img, const pixels& width, const pixels& height) = 0;
		virtual void paintString(const std::string& text) = 0;
		virtual void paintBackground(colorref, const pixels& width, const pixels& height) = 0;
		virtual void paintBorder(node*) = 0;
		virtual size measureString(const std::string& text) = 0;
		virtual pixels fontBaseline() = 0;

		virtual bool visible(node*) const = 0;
		virtual style_handle applyStyle(node*) = 0;
		virtual void restoreStyle(style_handle) = 0;

		virtual ratio trueZoom() const = 0;
	};

	class push_origin {
		painter* m_painter;
		point orig;
	public:
		explicit push_origin(painter* paint) : m_painter(paint), orig(paint->getOrigin())
		{
		}

		~push_origin()
		{
			m_painter->setOrigin(orig);
		}
	};
};<commit_msg>[JIRDESK-79] Adding box layers<commit_after>/*
 * Copyright (C) 2015 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#pragma once

#include <string>

#include <gui/types.hpp>

namespace gui {
	struct image_ref;
	struct node;
	struct style_save { int __unused; };
	using style_handle = style_save*;

	struct point {
		pixels x;
		pixels y;

		point() : x(0), y(0) {}
		point(const pixels& x, const pixels& y) : x(x), y(y) {}
		point(const point&) = default;
		point& operator=(const point&) = default;
		point(point&&) = default;
		point& operator=(point&&) = default;
	};

	struct size {
		pixels width;
		pixels height;

		size() : width(0), height(0) {}
		size(const pixels& width, const pixels& height) : width(width), height(height) {}
		size(const size&) = default;
		size& operator=(const size&) = default;
		size(size&&) = default;
		size& operator=(size&&) = default;

		bool empty() const
		{
			return !width.value() || !height.value();
		}
	};

	inline point operator + (const point& lhs, const point& rhs) {
		return{ lhs.x + rhs.x, lhs.y + rhs.y };
	}

	inline point operator + (const point& lhs, const size& rhs) {
		return{ lhs.x + rhs.width, lhs.y + rhs.height };
	}

	inline size operator - (const point& lhs, const point& rhs) {
		return{ std::abs((lhs.x - rhs.x).value()), std::abs((lhs.y - rhs.y).value()) };
	}

	struct box {
		pixels top;
		pixels right;
		pixels left;
		pixels bottom;

		box() = default;
		box(const box&) = default;
		box& operator=(const box&) = default;
		box(box&&) = default;
		box& operator=(box&&) = default;

		// this constructors takes top, right, bottom and left,
		// with values filled like in CSS
		box(const pixels& top, const pixels& right, const pixels& bottom, const pixels& left)
			: top(top)
			, right(right)
			, bottom(bottom)
			, left(left)
		{
		}

		// this constructors takes top, right and bottom,
		// with missing value filled like in CSS
		box(const pixels& top, const pixels& right, const pixels& bottom)
			: top(top)
			, right(right)
			, bottom(bottom)
			, left(right)
		{
		}

		// this constructors takes top and right,
		// with missing values filled like in CSS
		box(const pixels& top, const pixels& right)
			: top(top)
			, right(right)
			, bottom(top)
			, left(right)
		{
		}

		// this constructors takes only top,
		// with missing values filled like in CSS
		box(const pixels& top)
			: top(top)
			, right(top)
			, bottom(top)
			, left(top)
		{
		}
	};

	struct rect {
		gui::point origin;
		gui::size size;

		rect() = default;
		rect(const gui::point& topleft, const gui::point& bottomright) : origin(topleft), size(bottomright - topleft) {}
		rect(const gui::point& origin, const gui::size& size) : origin(origin), size(size) {}
		rect(const rect&) = default;
		rect& operator=(const rect&) = default;
		rect(rect&&) = default;
		rect& operator=(rect&&) = default;
	};

	struct reach {
		rect position;
		box values;

		reach() = default;
		reach(const rect& position, const box& values) : position(position), values(values) {}
		reach(const reach&) = default;
		reach& operator=(const reach&) = default;
		reach(reach&&) = default;
		reach& operator=(reach&&) = default;
	};

	struct css_box {
		box margin;
		box border;
		box padding;

		css_box() = default;
		css_box(const box& margin, const box& border, const box& padding) : margin(margin), border(border), padding(padding) {}
		css_box(const css_box&) = default;
		css_box& operator=(const css_box&) = default;
		css_box(css_box&&) = default;
		css_box& operator=(css_box&&) = default;
	};

	struct ratio {
		int num;
		int denom;

		long double scaleD(const pixels& px) const
		{
			return num * px.value() / denom;
		}

		float scaleF(const pixels& px) const
		{
			return (float)(num * px.value() / denom);
		}

		long scaleL(const pixels& px) const
		{
			return (long)(0.5 + num * px.value() / denom);
		}

		int scaleI(const pixels& px) const
		{
			return (int)(0.5 + num * px.value() / denom);
		}

		pixels invert(int value) const {
			return (long double)value * denom / num;
		}

		pixels invert(double value) const {
			return (long double)value * denom / num;
		}

		pixels invert(long double value) const {
			return value * denom / num;
		}

		static int GCD(int a, int b) {
			if (!b)
				return a;

			return GCD(b, a % b);
		}

		ratio gcd() const {
			auto factor = GCD(num, denom);
			return{ num / factor, denom / factor };
		}
	};

	inline ratio operator * (const ratio& lhs, const ratio& rhs)
	{
		auto out = lhs.gcd();
		auto right = rhs.gcd();

		auto gcd = ratio::GCD(out.num, right.denom);
		out.num /= gcd;
		right.denom /= gcd;

		gcd = ratio::GCD(right.num, out.denom);
		right.num /= gcd;
		out.denom /= gcd;

		out.num *= right.num;
		out.denom *= right.denom;

		return out;
	}

	struct painter {
		virtual ~painter() {}
		virtual void moveOrigin(const pixels& x, const pixels& y) = 0;
		void moveOrigin(const point& pt) { moveOrigin(pt.x, pt.y); }
		virtual point getOrigin() const = 0;
		virtual void setOrigin(const point& orig) = 0;
		virtual void paintImage(const image_ref* img, const pixels& width, const pixels& height) = 0;
		virtual void paintString(const std::string& text) = 0;
		virtual void paintBackground(colorref, const pixels& width, const pixels& height) = 0;
		virtual void paintBorder(node*) = 0;
		virtual size measureString(const std::string& text) = 0;
		virtual pixels fontBaseline() = 0;

		virtual bool visible(node*) const = 0;
		virtual style_handle applyStyle(node*) = 0;
		virtual void restoreStyle(style_handle) = 0;

		virtual ratio trueZoom() const = 0;
	};

	class push_origin {
		painter* m_painter;
		point orig;
	public:
		explicit push_origin(painter* paint) : m_painter(paint), orig(paint->getOrigin())
		{
		}

		~push_origin()
		{
			m_painter->setOrigin(orig);
		}
	};
};<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Max Kellermann <max@duempel.org>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 CONST_BUFFER_HPP
#define CONST_BUFFER_HPP

#include <inline/compiler.h>

#include <cstddef>

#ifndef NDEBUG
#include <assert.h>
#endif

/**
 * A reference to a memory area that is read-only.
 */
template<typename T>
struct ConstBuffer {
	typedef size_t size_type;
	typedef const T *pointer_type;
	typedef pointer_type const_pointer_type;
	typedef pointer_type iterator;
	typedef pointer_type const_iterator;

	pointer_type data;
	size_type size;

	ConstBuffer() = default;

	constexpr ConstBuffer(std::nullptr_t):data(nullptr), size(0) {}

	constexpr ConstBuffer(pointer_type _data, size_type _size)
		:data(_data), size(_size) {}

	constexpr static ConstBuffer Null() {
		return ConstBuffer(nullptr, 0);
	}

	/**
	 * Cast a ConstBuffer<void> to a ConstBuffer<T>.  A "void"
	 * buffer records its size in bytes, and when casting to "T",
	 * the assertion below ensures that the size is a multiple of
	 * sizeof(T).
	 */
#ifdef NDEBUG
	constexpr
#endif
	static ConstBuffer<T> FromVoid(ConstBuffer<void> other) {
		static_assert(sizeof(T) > 0, "Empty base type");
#ifndef NDEBUG
		assert(other.size % sizeof(T) == 0);
#endif
		return ConstBuffer<T>(pointer_type(other.data),
				      other.size / sizeof(T));
	}

	constexpr ConstBuffer<void> ToVoid() const {
		static_assert(sizeof(T) > 0, "Empty base type");
		return ConstBuffer<void>(data, size * sizeof(T));
	}

	constexpr bool IsNull() const {
		return data == nullptr;
	}

	constexpr bool IsEmpty() const {
		return size == 0;
	}

	constexpr iterator begin() const {
		return data;
	}

	constexpr iterator end() const {
		return data + size;
	}

	constexpr const_iterator cbegin() const {
		return data;
	}

	constexpr const_iterator cend() const {
		return data + size;
	}

	constexpr operator ConstBuffer<void>() const {
		return { data, size };
	}
};

#endif
<commit_msg>util/ConstBuffer: copy latest version from upstream<commit_after>/*
 * Copyright (C) 2013 Max Kellermann <max@duempel.org>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 CONST_BUFFER_HPP
#define CONST_BUFFER_HPP

#include <inline/compiler.h>

#include <cstddef>

#ifndef NDEBUG
#include <assert.h>
#endif

template<typename T>
struct ConstBuffer;

template<>
struct ConstBuffer<void> {
	typedef size_t size_type;
	typedef const void *pointer_type;
	typedef pointer_type const_pointer_type;
	typedef pointer_type iterator;
	typedef pointer_type const_iterator;

	pointer_type data;
	size_type size;

	ConstBuffer() = default;

	constexpr ConstBuffer(std::nullptr_t):data(nullptr), size(0) {}

	constexpr ConstBuffer(pointer_type _data, size_type _size)
		:data(_data), size(_size) {}

	constexpr static ConstBuffer Null() {
		return ConstBuffer(nullptr, 0);
	}

	constexpr static ConstBuffer<void> FromVoid(ConstBuffer<void> other) {
		return other;
	}

	constexpr ConstBuffer<void> ToVoid() const {
		return *this;
	}

	constexpr bool IsNull() const {
		return data == nullptr;
	}

	constexpr bool IsEmpty() const {
		return size == 0;
	}
};

/**
 * A reference to a memory area that is read-only.
 */
template<typename T>
struct ConstBuffer {
	typedef size_t size_type;
	typedef const T *pointer_type;
	typedef pointer_type const_pointer_type;
	typedef pointer_type iterator;
	typedef pointer_type const_iterator;

	pointer_type data;
	size_type size;

	ConstBuffer() = default;

	constexpr ConstBuffer(std::nullptr_t):data(nullptr), size(0) {}

	constexpr ConstBuffer(pointer_type _data, size_type _size)
		:data(_data), size(_size) {}

	constexpr static ConstBuffer Null() {
		return ConstBuffer(nullptr, 0);
	}

	/**
	 * Cast a ConstBuffer<void> to a ConstBuffer<T>.  A "void"
	 * buffer records its size in bytes, and when casting to "T",
	 * the assertion below ensures that the size is a multiple of
	 * sizeof(T).
	 */
#ifdef NDEBUG
	constexpr
#endif
	static ConstBuffer<T> FromVoid(ConstBuffer<void> other) {
		static_assert(sizeof(T) > 0, "Empty base type");
#ifndef NDEBUG
		assert(other.size % sizeof(T) == 0);
#endif
		return ConstBuffer<T>(pointer_type(other.data),
				      other.size / sizeof(T));
	}

	constexpr ConstBuffer<void> ToVoid() const {
		static_assert(sizeof(T) > 0, "Empty base type");
		return ConstBuffer<void>(data, size * sizeof(T));
	}

	constexpr bool IsNull() const {
		return data == nullptr;
	}

	constexpr bool IsEmpty() const {
		return size == 0;
	}

	constexpr iterator begin() const {
		return data;
	}

	constexpr iterator end() const {
		return data + size;
	}

	constexpr const_iterator cbegin() const {
		return data;
	}

	constexpr const_iterator cend() const {
		return data + size;
	}

#ifdef NDEBUG
	constexpr
#endif
	const T &operator[](size_type i) const {
#ifndef NDEBUG
		assert(i < size);
#endif

		return data[i];
	}
};

#endif
<|endoftext|>


<commit_before>#include "GLMaterial.h"
#include "GLTexture.h"
#include "GLShaderManager.h"
#include "Package.h"

namespace {

    static const std::string constantVsh = R"GLSL(
        attribute vec3 aVertexPosition;
        attribute vec2 aVertexUV;
        uniform mat4 uProjMatrix;
        uniform mat4 uMVMatrix;
        varying vec2 vUV;

        void main(void) {
            vUV = aVertexUV;
            gl_Position = uProjMatrix * (uMVMatrix * vec4(aVertexPosition, 1.0));
        }
    )GLSL";

    static const std::string constantFsh = R"GLSL(
        precision mediump float;
        varying vec2 vUV;

        #ifdef EMISSION_TEXTURE
        uniform sampler2D uEmissionTex;
        #else
        uniform vec4 uEmissionColor;
        #endif

        void main(void) {
        #ifdef EMISSION_TEXTURE
            vec4 emission = texture2D(uEmissionTex, vUV);
        #else
            vec4 emission = uEmissionColor;
        #endif

            vec4 color = emission;
            if (color.a == 0.0) {
                discard;
            }
            gl_FragColor = color;
        }
    )GLSL";

    static const std::string prebakedVsh = R"GLSL(
        attribute vec3 aVertexPosition;
        attribute vec2 aVertexUV;
        attribute vec4 aVertexColor;
        uniform mat4 uProjMatrix;
        uniform mat4 uMVMatrix;
        varying vec2 vUV;
        varying lowp vec4 vColor;

        void main(void) {
            vUV = aVertexUV;
            vColor = aVertexColor;
            gl_Position = uProjMatrix * (uMVMatrix * vec4(aVertexPosition, 1.0));
        }
    )GLSL";

    static const std::string prebakedFsh = R"GLSL(
        precision mediump float;
        varying vec2 vUV;
        varying lowp vec4 vColor;

        #ifdef DIFFUSE_TEXTURE
        uniform sampler2D uDiffuseTex;
        #else
        uniform vec4 uDiffuseColor;
        #endif

        void main(void) {
        #ifdef DIFFUSE_TEXTURE
            vec4 diffuse = texture2D(uDiffuseTex, vUV);
        #else
            vec4 diffuse = uDiffuseColor;
        #endif

            vec4 color = diffuse * vColor;
            if (color.a == 0.0) {
                discard;
            }
            gl_FragColor = color;
        }
    )GLSL";

    static const std::string lambertPhongBlinnVsh = R"GLSL(
        attribute vec3 aVertexPosition;
        attribute vec2 aVertexUV;
        attribute vec3 aVertexNormal;
        uniform mat4 uProjMatrix;
        uniform mat4 uMVMatrix;
        uniform mat4 uInvTransMVMatrix;
        varying vec2 vUV;
        varying vec3 vNormal;
        varying vec3 vPos;

        void main(void) {
            vec4 pos = uMVMatrix * vec4(aVertexPosition, 1.0);
            vUV = aVertexUV;
            vNormal = vec3(uInvTransMVMatrix * vec4(aVertexNormal, 0.0));
            vPos = vec3(pos) / pos.w;
            gl_Position = uProjMatrix * pos;
        }
    )GLSL";

    static const std::string lambertPhongBlinnFsh = R"GLSL(
        precision mediump float;
        varying vec2 vUV;
        varying vec3 vNormal;
        varying vec3 vPos;

        uniform vec4 uAmbientLightColor;
        uniform vec3 uMainLightDir;
        uniform vec4 uMainLightColor;

        #ifdef EMISSION_TEXTURE
        uniform sampler2D uEmissionTex;
        #else
        uniform vec4 uEmissionColor;
        #endif

        #ifdef AMBIENT_TEXTURE
        uniform sampler2D uAmbientTex;
        #else
        uniform vec4 uAmbientColor;
        #endif

        #ifdef DIFFUSE_TEXTURE
        uniform sampler2D uDiffuseTex;
        #else
        uniform vec4 uDiffuseColor;
        #endif

        #ifdef TRANSPARENT_TEXTURE
        uniform sampler2D uTransparentTex;
        #else
        uniform vec4 uTransparentColor;
        #endif
        uniform float uTransparency;

        #if defined(BLINN) || defined(PHONG)
        #ifdef SPECULAR_TEXTURE
        uniform sampler2D uSpecularTex;
        #else
        uniform vec4 uSpecularColor;
        #endif
        uniform float uShininess;
        #endif

        void main(void) {
        #ifdef EMISSION_TEXTURE
            vec4 emission = texture2D(uEmissionTex, vUV);
        #else
            vec4 emission = uEmissionColor;
        #endif

        #ifdef AMBIENT_TEXTURE
            vec4 ambient = texture2D(uAmbientTex, vUV);
        #else
            vec4 ambient = uAmbientColor;
        #endif

        #ifdef DIFFUSE_TEXTURE
            vec4 diffuse = texture2D(uDiffuseTex, vUV);
        #else
            vec4 diffuse = uDiffuseColor;
        #endif

            vec3 n = normalize(vNormal);
            float n_dot_l = max(dot(n, uMainLightDir), 0.0);

            vec4 color = emission + (ambient + diffuse) * uAmbientLightColor + n_dot_l * diffuse * uMainLightColor;

        #if defined(BLINN) || defined(PHONG)
            if (n_dot_l > 0.0) {
            #ifdef SPECULAR_TEXTURE
                vec4 specular = texture2D(uSpecularTex, vUV);
            #else
                vec4 specular = uSpecularColor;
            #endif

            #ifdef BLINN
                vec3 v = normalize(-vPos);
                vec3 h = normalize(v + uMainLightDir);
                float refl = pow(max(dot(h, n), 0.0), uShininess);
            #else
                vec3 v = normalize(-vPos);
                vec3 r = reflect(uMainLightDir, n);
                float refl = pow(max(dot(r, v), 0.0), uShininess);
            #endif

                color = color + refl * specular * uMainLightColor;
            }
        #endif

        #ifdef TRANSPARENT_TEXTURE
            vec4 transparent = texture2D(uTransparentTex, vUV);
        #else
            vec4 transparent = uTransparentColor;
        #endif
            vec4 opacity = vec4(1.0, 1.0, 1.0, 1.0) - transparent;
            float alpha = max(opacity.r, max(opacity.g, opacity.b));

            if (alpha == 0.0) {
                discard;
            }
            gl_FragColor = vec4((color * opacity).rgb * alpha, alpha);
        }
    )GLSL";

}

namespace carto { namespace nml {

    GLMaterial::GLColorOrTexture::GLColorOrTexture() :
        textureId(),
        texture(),
        color(cglib::vec4<float>::zero())
    {
    }

    GLMaterial::GLColorOrTexture::GLColorOrTexture(const ColorOrTexture& colorOrTexture, const std::map<std::string, std::shared_ptr<GLTexture>>& textureMap) :
        textureId(),
        texture(),
        color(cglib::vec4<float>::zero())
    {
        if (colorOrTexture.has_texture_id()) {
            textureId = colorOrTexture.texture_id();
            auto it = textureMap.find(colorOrTexture.texture_id());
            if (it != textureMap.end()) {
                texture = it->second;
            }
        }
        if (colorOrTexture.has_color()) {
            ColorRGBA c = colorOrTexture.color();
            color = cglib::vec4<float>(c.r(), c.g(),c.b(), c.a());
        }
    }

    GLMaterial::GLMaterial(const Material& material, const std::map<std::string, std::shared_ptr<GLTexture>>& textureMap) :
        _type(Material::CONSTANT),
        _culling(Material::NONE),
        _opaqueMode(Material::OPAQUE),
        _emission(),
        _ambient(),
        _diffuse(),
        _transparent(),
        _transparency(),
        _specular(),
        _shininess(),
        _glProgramId()
    {
        _type = material.type();
        _culling = material.culling();
        _opaqueMode = material.has_opaque_mode() ? material.opaque_mode() : Material::OPAQUE;
        _emission = material.has_emission() ? GLColorOrTexture(material.emission(), textureMap) : GLColorOrTexture();
        _ambient = material.has_ambient() ? GLColorOrTexture(material.ambient(), textureMap) : GLColorOrTexture();
        _diffuse = material.has_diffuse() ? GLColorOrTexture(material.diffuse(), textureMap) : GLColorOrTexture();
        _transparent = material.has_transparent() ? GLColorOrTexture(material.transparent(), textureMap) : GLColorOrTexture();
        _transparency = material.has_transparency() ? material.transparency() : 0.0f;
        _specular = material.has_specular() ? GLColorOrTexture(material.specular(), textureMap) : GLColorOrTexture();
        _shininess = material.has_shininess() ? material.shininess() : 0.0f;
    }

    void GLMaterial::create(GLShaderManager& shaderManager) {
        std::set<std::string> defs;
        if (!_emission.textureId.empty()) {
            defs.insert("EMISSION_TEXTURE");
        }
        if (!_ambient.textureId.empty()) {
            defs.insert("AMBIENT_TEXTURE");
        }
        if (!_diffuse.textureId.empty()) {
            defs.insert("DIFFUSE_TEXTURE");
        }
        if (!_transparent.textureId.empty()) {
            defs.insert("TRANSPARENT_TEXTURE");
        }
        if (!_specular.textureId.empty()) {
            defs.insert("SPECULAR_TEXTURE");
        }

        switch (_type) {
        case Material::CONSTANT:
            _glProgramId = shaderManager.createProgram(constantVsh, constantFsh, defs);
            break;
        case Material::PREBAKED:
            _glProgramId = shaderManager.createProgram(prebakedVsh, prebakedFsh, defs);
            break;
        case Material::LAMBERT:
            _glProgramId = shaderManager.createProgram(lambertPhongBlinnVsh, lambertPhongBlinnFsh, defs);
            break;
        case Material::PHONG:
            defs.insert("PHONG");
            _glProgramId = shaderManager.createProgram(lambertPhongBlinnVsh, lambertPhongBlinnFsh, defs);
            break;
        case Material::BLINN:
            defs.insert("BLINN");
            _glProgramId = shaderManager.createProgram(lambertPhongBlinnVsh, lambertPhongBlinnFsh, defs);
            break;
        default:
            assert(false);
        }
    }

    void GLMaterial::dispose() {
    }

    int GLMaterial::getCulling() const {
        return _culling;
    }

    void GLMaterial::replaceTexture(const std::string &textureId, const std::shared_ptr<GLTexture>& texture) {
        GLColorOrTexture* channels[] = {
            &_emission,
            &_ambient,
            &_diffuse,
            &_specular,
            nullptr
        };

        for (int i = 0; channels[i]; i++) {
            if (channels[i]->textureId == textureId) {
                channels[i]->texture = texture;
            }
        }
    }

    void GLMaterial::bind(const RenderState& renderState, const cglib::mat4x4<float>& mvMatrix, const cglib::mat4x4<float>& invTransMVMatrix) {
        glDepthMask(_opaqueMode == Material::OPAQUE ? GL_TRUE : GL_FALSE);

        glUseProgram(_glProgramId);

        glUniformMatrix4fv(glGetUniformLocation(_glProgramId, "uProjMatrix"), 1, GL_FALSE, renderState.projMatrix.data());
        glUniformMatrix4fv(glGetUniformLocation(_glProgramId, "uMVMatrix"), 1, GL_FALSE, mvMatrix.data());

        if (_culling == Material::NONE) {
            glDisable(GL_CULL_FACE);
        } else {
            glEnable(GL_CULL_FACE);
            glCullFace(_culling == Material::FRONT ? GL_FRONT : GL_BACK);
        }

        if (_type != Material::PREBAKED) {
            if (_emission.texture) {
                glUniform1i(glGetUniformLocation(_glProgramId, "uEmissionTex"), 0);
                _emission.texture->bind(0);
            } else {
                glUniform4fv(glGetUniformLocation(_glProgramId, "uEmissionColor"), 1, _emission.color.data());
            }
        }

        if (_type != Material::CONSTANT) {
            if (_diffuse.texture) {
                glUniform1i(glGetUniformLocation(_glProgramId, "uDiffuseTex"), 1);
                _diffuse.texture->bind(1);
            } else {
                glUniform4fv(glGetUniformLocation(_glProgramId, "uDiffuseColor"), 1, _diffuse.color.data());
            }

            if (_transparent.texture) {
                glUniform1i(glGetUniformLocation(_glProgramId, "uTransparentTex"), 2);
                _transparent.texture->bind(2);
            } else {
                glUniform4fv(glGetUniformLocation(_glProgramId, "uTransparentColor"), 1, _transparent.color.data());
            }
            glUniform1f(glGetUniformLocation(_glProgramId, "uTransparency"), 1.0f);

            if (_type != Material::PREBAKED) {
                if (_ambient.texture) {
                    glUniform1i(glGetUniformLocation(_glProgramId, "uAmbientTex"), 3);
                    _ambient.texture->bind(3);
                } else {
                    glUniform4fv(glGetUniformLocation(_glProgramId, "uAmbientColor"), 1, _ambient.color.data());
                }

                if (_type != Material::LAMBERT) {
                    if (_specular.texture) {
                        glUniform1i(glGetUniformLocation(_glProgramId, "uSpecularTex"), 4);
                        _specular.texture->bind(4);
                    } else {
                        glUniform4fv(glGetUniformLocation(_glProgramId, "uSpecularColor"), 1, _specular.color.data());
                    }
                    glUniform1f(glGetUniformLocation(_glProgramId, "uShininess"), _shininess);
                }

                glUniformMatrix4fv(glGetUniformLocation(_glProgramId, "uInvTransMVMatrix"), 1, GL_FALSE, invTransMVMatrix.data());

                glUniform4fv(glGetUniformLocation(_glProgramId, "uAmbientLightColor"), 1, renderState.ambientLightColor.data());
                glUniform4fv(glGetUniformLocation(_glProgramId, "uMainLightColor"), 1, renderState.mainLightColor.data());
                glUniform3fv(glGetUniformLocation(_glProgramId, "uMainLightDir"), 1, renderState.mainLightDir.data());
            }
        }
    }

} }
<commit_msg>Increase fragment shader precision when rendering NML models<commit_after>#include "GLMaterial.h"
#include "GLTexture.h"
#include "GLShaderManager.h"
#include "Package.h"

namespace {

    static const std::string constantVsh = R"GLSL(
        attribute vec3 aVertexPosition;
        attribute vec2 aVertexUV;
        uniform mat4 uProjMatrix;
        uniform mat4 uMVMatrix;
        varying vec2 vUV;

        void main(void) {
            vUV = aVertexUV;
            gl_Position = uProjMatrix * (uMVMatrix * vec4(aVertexPosition, 1.0));
        }
    )GLSL";

    static const std::string constantFsh = R"GLSL(
        precision mediump float;
        varying vec2 vUV;

        #ifdef EMISSION_TEXTURE
        uniform sampler2D uEmissionTex;
        #else
        uniform vec4 uEmissionColor;
        #endif

        void main(void) {
        #ifdef EMISSION_TEXTURE
            vec4 emission = texture2D(uEmissionTex, vUV);
        #else
            vec4 emission = uEmissionColor;
        #endif

            vec4 color = emission;
            if (color.a == 0.0) {
                discard;
            }
            gl_FragColor = color;
        }
    )GLSL";

    static const std::string prebakedVsh = R"GLSL(
        attribute vec3 aVertexPosition;
        attribute vec2 aVertexUV;
        attribute vec4 aVertexColor;
        uniform mat4 uProjMatrix;
        uniform mat4 uMVMatrix;
        varying vec2 vUV;
        varying lowp vec4 vColor;

        void main(void) {
            vUV = aVertexUV;
            vColor = aVertexColor;
            gl_Position = uProjMatrix * (uMVMatrix * vec4(aVertexPosition, 1.0));
        }
    )GLSL";

    static const std::string prebakedFsh = R"GLSL(
        precision mediump float;
        varying vec2 vUV;
        varying lowp vec4 vColor;

        #ifdef DIFFUSE_TEXTURE
        uniform sampler2D uDiffuseTex;
        #else
        uniform vec4 uDiffuseColor;
        #endif

        void main(void) {
        #ifdef DIFFUSE_TEXTURE
            vec4 diffuse = texture2D(uDiffuseTex, vUV);
        #else
            vec4 diffuse = uDiffuseColor;
        #endif

            vec4 color = diffuse * vColor;
            if (color.a == 0.0) {
                discard;
            }
            gl_FragColor = color;
        }
    )GLSL";

    static const std::string lambertPhongBlinnVsh = R"GLSL(
        attribute vec3 aVertexPosition;
        attribute vec2 aVertexUV;
        attribute vec3 aVertexNormal;
        uniform mat4 uProjMatrix;
        uniform mat4 uMVMatrix;
        uniform mat4 uInvTransMVMatrix;
        varying vec2 vUV;
        varying vec3 vNormal;
        varying vec3 vPos;

        void main(void) {
            vec4 pos = uMVMatrix * vec4(aVertexPosition, 1.0);
            vUV = aVertexUV;
            vNormal = vec3(uInvTransMVMatrix * vec4(aVertexNormal, 0.0));
            vPos = vec3(pos) / pos.w;
            gl_Position = uProjMatrix * pos;
        }
    )GLSL";

    static const std::string lambertPhongBlinnFsh = R"GLSL(
        #ifdef GL_FRAGMENT_PRECISION_HIGH
        precision highp float;
        #else
        precision mediump float;
        #endif
        varying vec2 vUV;
        varying vec3 vNormal;
        varying vec3 vPos;

        uniform vec4 uAmbientLightColor;
        uniform vec3 uMainLightDir;
        uniform vec4 uMainLightColor;

        #ifdef EMISSION_TEXTURE
        uniform sampler2D uEmissionTex;
        #else
        uniform vec4 uEmissionColor;
        #endif

        #ifdef AMBIENT_TEXTURE
        uniform sampler2D uAmbientTex;
        #else
        uniform vec4 uAmbientColor;
        #endif

        #ifdef DIFFUSE_TEXTURE
        uniform sampler2D uDiffuseTex;
        #else
        uniform vec4 uDiffuseColor;
        #endif

        #ifdef TRANSPARENT_TEXTURE
        uniform sampler2D uTransparentTex;
        #else
        uniform vec4 uTransparentColor;
        #endif
        uniform float uTransparency;

        #if defined(BLINN) || defined(PHONG)
        #ifdef SPECULAR_TEXTURE
        uniform sampler2D uSpecularTex;
        #else
        uniform vec4 uSpecularColor;
        #endif
        uniform float uShininess;
        #endif

        void main(void) {
        #ifdef EMISSION_TEXTURE
            vec4 emission = texture2D(uEmissionTex, vUV);
        #else
            vec4 emission = uEmissionColor;
        #endif

        #ifdef AMBIENT_TEXTURE
            vec4 ambient = texture2D(uAmbientTex, vUV);
        #else
            vec4 ambient = uAmbientColor;
        #endif

        #ifdef DIFFUSE_TEXTURE
            vec4 diffuse = texture2D(uDiffuseTex, vUV);
        #else
            vec4 diffuse = uDiffuseColor;
        #endif

            vec3 n = normalize(vNormal);
            float n_dot_l = max(dot(n, uMainLightDir), 0.0);

            vec4 color = emission + (ambient + diffuse) * uAmbientLightColor + n_dot_l * diffuse * uMainLightColor;

        #if defined(BLINN) || defined(PHONG)
            if (n_dot_l > 0.0) {
            #ifdef SPECULAR_TEXTURE
                vec4 specular = texture2D(uSpecularTex, vUV);
            #else
                vec4 specular = uSpecularColor;
            #endif

            #ifdef BLINN
                vec3 v = normalize(-vPos);
                vec3 h = normalize(v + uMainLightDir);
                float refl = pow(max(dot(h, n), 0.0), uShininess);
            #else
                vec3 v = normalize(-vPos);
                vec3 r = reflect(uMainLightDir, n);
                float refl = pow(max(dot(r, v), 0.0), uShininess);
            #endif

                color = color + refl * specular * uMainLightColor;
            }
        #endif

        #ifdef TRANSPARENT_TEXTURE
            vec4 transparent = texture2D(uTransparentTex, vUV);
        #else
            vec4 transparent = uTransparentColor;
        #endif
            vec4 opacity = vec4(1.0, 1.0, 1.0, 1.0) - transparent;
            float alpha = max(opacity.r, max(opacity.g, opacity.b));

            if (alpha == 0.0) {
                discard;
            }
            gl_FragColor = vec4((color * opacity).rgb * alpha, alpha);
        }
    )GLSL";

}

namespace carto { namespace nml {

    GLMaterial::GLColorOrTexture::GLColorOrTexture() :
        textureId(),
        texture(),
        color(cglib::vec4<float>::zero())
    {
    }

    GLMaterial::GLColorOrTexture::GLColorOrTexture(const ColorOrTexture& colorOrTexture, const std::map<std::string, std::shared_ptr<GLTexture>>& textureMap) :
        textureId(),
        texture(),
        color(cglib::vec4<float>::zero())
    {
        if (colorOrTexture.has_texture_id()) {
            textureId = colorOrTexture.texture_id();
            auto it = textureMap.find(colorOrTexture.texture_id());
            if (it != textureMap.end()) {
                texture = it->second;
            }
        }
        if (colorOrTexture.has_color()) {
            ColorRGBA c = colorOrTexture.color();
            color = cglib::vec4<float>(c.r(), c.g(),c.b(), c.a());
        }
    }

    GLMaterial::GLMaterial(const Material& material, const std::map<std::string, std::shared_ptr<GLTexture>>& textureMap) :
        _type(Material::CONSTANT),
        _culling(Material::NONE),
        _opaqueMode(Material::OPAQUE),
        _emission(),
        _ambient(),
        _diffuse(),
        _transparent(),
        _transparency(),
        _specular(),
        _shininess(),
        _glProgramId()
    {
        _type = material.type();
        _culling = material.culling();
        _opaqueMode = material.has_opaque_mode() ? material.opaque_mode() : Material::OPAQUE;
        _emission = material.has_emission() ? GLColorOrTexture(material.emission(), textureMap) : GLColorOrTexture();
        _ambient = material.has_ambient() ? GLColorOrTexture(material.ambient(), textureMap) : GLColorOrTexture();
        _diffuse = material.has_diffuse() ? GLColorOrTexture(material.diffuse(), textureMap) : GLColorOrTexture();
        _transparent = material.has_transparent() ? GLColorOrTexture(material.transparent(), textureMap) : GLColorOrTexture();
        _transparency = material.has_transparency() ? material.transparency() : 0.0f;
        _specular = material.has_specular() ? GLColorOrTexture(material.specular(), textureMap) : GLColorOrTexture();
        _shininess = material.has_shininess() ? material.shininess() : 0.0f;
    }

    void GLMaterial::create(GLShaderManager& shaderManager) {
        std::set<std::string> defs;
        if (!_emission.textureId.empty()) {
            defs.insert("EMISSION_TEXTURE");
        }
        if (!_ambient.textureId.empty()) {
            defs.insert("AMBIENT_TEXTURE");
        }
        if (!_diffuse.textureId.empty()) {
            defs.insert("DIFFUSE_TEXTURE");
        }
        if (!_transparent.textureId.empty()) {
            defs.insert("TRANSPARENT_TEXTURE");
        }
        if (!_specular.textureId.empty()) {
            defs.insert("SPECULAR_TEXTURE");
        }

        switch (_type) {
        case Material::CONSTANT:
            _glProgramId = shaderManager.createProgram(constantVsh, constantFsh, defs);
            break;
        case Material::PREBAKED:
            _glProgramId = shaderManager.createProgram(prebakedVsh, prebakedFsh, defs);
            break;
        case Material::LAMBERT:
            _glProgramId = shaderManager.createProgram(lambertPhongBlinnVsh, lambertPhongBlinnFsh, defs);
            break;
        case Material::PHONG:
            defs.insert("PHONG");
            _glProgramId = shaderManager.createProgram(lambertPhongBlinnVsh, lambertPhongBlinnFsh, defs);
            break;
        case Material::BLINN:
            defs.insert("BLINN");
            _glProgramId = shaderManager.createProgram(lambertPhongBlinnVsh, lambertPhongBlinnFsh, defs);
            break;
        default:
            assert(false);
        }
    }

    void GLMaterial::dispose() {
    }

    int GLMaterial::getCulling() const {
        return _culling;
    }

    void GLMaterial::replaceTexture(const std::string &textureId, const std::shared_ptr<GLTexture>& texture) {
        GLColorOrTexture* channels[] = {
            &_emission,
            &_ambient,
            &_diffuse,
            &_specular,
            nullptr
        };

        for (int i = 0; channels[i]; i++) {
            if (channels[i]->textureId == textureId) {
                channels[i]->texture = texture;
            }
        }
    }

    void GLMaterial::bind(const RenderState& renderState, const cglib::mat4x4<float>& mvMatrix, const cglib::mat4x4<float>& invTransMVMatrix) {
        glDepthMask(_opaqueMode == Material::OPAQUE ? GL_TRUE : GL_FALSE);

        glUseProgram(_glProgramId);

        glUniformMatrix4fv(glGetUniformLocation(_glProgramId, "uProjMatrix"), 1, GL_FALSE, renderState.projMatrix.data());
        glUniformMatrix4fv(glGetUniformLocation(_glProgramId, "uMVMatrix"), 1, GL_FALSE, mvMatrix.data());

        if (_culling == Material::NONE) {
            glDisable(GL_CULL_FACE);
        } else {
            glEnable(GL_CULL_FACE);
            glCullFace(_culling == Material::FRONT ? GL_FRONT : GL_BACK);
        }

        if (_type != Material::PREBAKED) {
            if (_emission.texture) {
                glUniform1i(glGetUniformLocation(_glProgramId, "uEmissionTex"), 0);
                _emission.texture->bind(0);
            } else {
                glUniform4fv(glGetUniformLocation(_glProgramId, "uEmissionColor"), 1, _emission.color.data());
            }
        }

        if (_type != Material::CONSTANT) {
            if (_diffuse.texture) {
                glUniform1i(glGetUniformLocation(_glProgramId, "uDiffuseTex"), 1);
                _diffuse.texture->bind(1);
            } else {
                glUniform4fv(glGetUniformLocation(_glProgramId, "uDiffuseColor"), 1, _diffuse.color.data());
            }

            if (_transparent.texture) {
                glUniform1i(glGetUniformLocation(_glProgramId, "uTransparentTex"), 2);
                _transparent.texture->bind(2);
            } else {
                glUniform4fv(glGetUniformLocation(_glProgramId, "uTransparentColor"), 1, _transparent.color.data());
            }
            glUniform1f(glGetUniformLocation(_glProgramId, "uTransparency"), 1.0f);

            if (_type != Material::PREBAKED) {
                if (_ambient.texture) {
                    glUniform1i(glGetUniformLocation(_glProgramId, "uAmbientTex"), 3);
                    _ambient.texture->bind(3);
                } else {
                    glUniform4fv(glGetUniformLocation(_glProgramId, "uAmbientColor"), 1, _ambient.color.data());
                }

                if (_type != Material::LAMBERT) {
                    if (_specular.texture) {
                        glUniform1i(glGetUniformLocation(_glProgramId, "uSpecularTex"), 4);
                        _specular.texture->bind(4);
                    } else {
                        glUniform4fv(glGetUniformLocation(_glProgramId, "uSpecularColor"), 1, _specular.color.data());
                    }
                    glUniform1f(glGetUniformLocation(_glProgramId, "uShininess"), _shininess);
                }

                glUniformMatrix4fv(glGetUniformLocation(_glProgramId, "uInvTransMVMatrix"), 1, GL_FALSE, invTransMVMatrix.data());

                glUniform4fv(glGetUniformLocation(_glProgramId, "uAmbientLightColor"), 1, renderState.ambientLightColor.data());
                glUniform4fv(glGetUniformLocation(_glProgramId, "uMainLightColor"), 1, renderState.mainLightColor.data());
                glUniform3fv(glGetUniformLocation(_glProgramId, "uMainLightDir"), 1, renderState.mainLightDir.data());
            }
        }
    }

} }
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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

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

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

#include "crown.h"
#include "memory.h"
#include "input.h"
#include "console_server.h"
#include "bundle_compiler.h"
#include "device.h"
#include "command_line.h"
#include "json_parser.h"
#include "keyboard.h"
#include "mouse.h"
#include "touch.h"
#include "main.h"
#include "audio.h"
#include "physics.h"
#include "disk_filesystem.h"
#include "config.h"
#include "math_utils.h"
#include <bgfx.h>

namespace crown
{
static void help(const char* msg = NULL)
{
	if (msg)
	{
		printf("Error: %s\n", msg);
	}

	printf(
		"Usage: crown [options]\n"
		"Options:\n\n"

		"  -h --help                  Show this help.\n"
		"  --bundle-dir <path>        Use <path> as the source directory for compiled resources.\n"
		"  --parent-window <handle>   Set the parent window <handle> of the main window.\n"
		"                             Used only by tools.\n"

		"\nAvailable only in debug and development builds:\n\n"

		"  --source-dir <path>        Use <path> as the source directory for resource compilation.\n"
		"  --compile                  Do a full compile of the resources.\n"
		"  --platform <platform>      Compile resources for the given <platform>.\n"
		"      Possible values for <platform> are:\n"
		"          linux\n"
		"          android\n"
		"          windows\n"
		"  --continue                 Continue the execution after the resource compilation step.\n"
		"  --host                     Read resources from a remote engine instance.\n"
		"  --wait-console             Wait for a console connection before starting up.\n"
	);
}

CommandLineSettings parse_command_line(int argc, char** argv)
{
	CommandLineSettings cls;
	cls.source_dir = NULL;
	cls.bundle_dir = NULL;
	cls.platform = NULL;
	cls.wait_console = false;
	cls.do_compile = false;
	cls.do_continue = false;
	cls.parent_window = 0;

	CommandLine cmd(argc, argv);

	if (cmd.has_argument("help", 'h'))
	{
		help();
		exit(EXIT_FAILURE);
	}

	cls.source_dir = cmd.get_parameter("source-dir");
	if (!cls.source_dir)
	{
		help("Source directory must be specified.");
		exit(EXIT_FAILURE);
	}

	cls.bundle_dir = cmd.get_parameter("bundle-dir");
	if (!cls.bundle_dir)
	{
		help("Bundle directory must be specified.");
		exit(EXIT_FAILURE);
	}

	cls.platform = cmd.get_parameter("platform");
	if (!cls.platform)
	{
		help("Platform must be specified.");
		exit(EXIT_FAILURE);
	}

	cls.platform = cmd.get_parameter("platform");
	cls.wait_console = cmd.has_argument("wait-console");
	cls.do_compile = cmd.has_argument("compile");
	cls.do_continue = cmd.has_argument("continue");

	const char* parent = cmd.get_parameter("parent-window");
	if (parent)
	{
		cls.parent_window = string::parse_uint(parent);
	}

	return cls;
}

ConfigSettings parse_config_file(Filesystem& fs)
{
	ConfigSettings cs;
	cs.console_port = 10001;
	cs.boot_package = 0;
	cs.boot_script = 0;
	cs.window_width = CROWN_DEFAULT_WINDOW_WIDTH;
	cs.window_height = CROWN_DEFAULT_WINDOW_HEIGHT;

	File* tmpfile = fs.open("crown.config", FOM_READ);
	JSONParser config(*tmpfile);
	fs.close(tmpfile);
	JSONElement root = config.root();

	JSONElement cport = root.key_or_nil("console_port");
	if (!cport.is_nil())
	{
		cs.console_port = (int16_t) cport.to_int();
	}

	JSONElement window_width = root.key_or_nil("window_width");
	if (!window_width.is_nil())
	{
		cs.window_width = math::max((uint16_t)1, (uint16_t)window_width.to_int());
	}

	JSONElement window_height = root.key_or_nil("window_height");
	if (!window_height.is_nil())
	{
		cs.window_height = math::max((uint16_t)1, (uint16_t)window_height.to_int());
	}

	cs.boot_script = root.key("boot_script").to_resource_id("lua").name;
	cs.boot_package = root.key("boot_package").to_resource_id("package").name;

	return cs;
}

bool init(Filesystem& fs, const ConfigSettings& cs)
{
	input_globals::init();
	audio_globals::init();
	physics_globals::init();
	bgfx::init();
	device_globals::init(fs, cs.boot_package, cs.boot_script);
	device()->init();
	return true;
}

void update()
{
	while (!process_events() && device()->is_running())
	{
#if defined(CROWN_DEBUG)
		console_server_globals::console().update();
#endif
		device()->update();
		input_globals::keyboard().update();
		input_globals::mouse().update();
		input_globals::touch().update();
	}
}

void shutdown()
{
	device()->shutdown();
	device_globals::shutdown();
	bgfx::shutdown();
	physics_globals::shutdown();
	audio_globals::shutdown();
	input_globals::shutdown();
}
} // namespace crown
<commit_msg>Require --platform only when compiling<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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

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

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

#include "crown.h"
#include "memory.h"
#include "input.h"
#include "console_server.h"
#include "bundle_compiler.h"
#include "device.h"
#include "command_line.h"
#include "json_parser.h"
#include "keyboard.h"
#include "mouse.h"
#include "touch.h"
#include "main.h"
#include "audio.h"
#include "physics.h"
#include "disk_filesystem.h"
#include "config.h"
#include "math_utils.h"
#include <bgfx.h>

namespace crown
{
static void help(const char* msg = NULL)
{
	if (msg)
	{
		printf("Error: %s\n", msg);
	}

	printf(
		"Usage: crown [options]\n"
		"Options:\n\n"

		"  -h --help                  Show this help.\n"
		"  --bundle-dir <path>        Use <path> as the source directory for compiled resources.\n"
		"  --parent-window <handle>   Set the parent window <handle> of the main window.\n"
		"                             Used only by tools.\n"

		"\nAvailable only in debug and development builds:\n\n"

		"  --source-dir <path>        Use <path> as the source directory for resource compilation.\n"
		"  --compile                  Do a full compile of the resources.\n"
		"  --platform <platform>      Compile resources for the given <platform>.\n"
		"      Possible values for <platform> are:\n"
		"          linux\n"
		"          android\n"
		"          windows\n"
		"  --continue                 Continue the execution after the resource compilation step.\n"
		"  --host                     Read resources from a remote engine instance.\n"
		"  --wait-console             Wait for a console connection before starting up.\n"
	);
}

CommandLineSettings parse_command_line(int argc, char** argv)
{
	CommandLineSettings cls;
	cls.source_dir = NULL;
	cls.bundle_dir = NULL;
	cls.platform = NULL;
	cls.wait_console = false;
	cls.do_compile = false;
	cls.do_continue = false;
	cls.parent_window = 0;

	CommandLine cmd(argc, argv);

	if (cmd.has_argument("help", 'h'))
	{
		help();
		exit(EXIT_FAILURE);
	}

	cls.source_dir = cmd.get_parameter("source-dir");
	if (!cls.source_dir)
	{
		help("Source directory must be specified.");
		exit(EXIT_FAILURE);
	}

	cls.bundle_dir = cmd.get_parameter("bundle-dir");
	if (!cls.bundle_dir)
	{
		help("Bundle directory must be specified.");
		exit(EXIT_FAILURE);
	}

	cls.platform = cmd.get_parameter("platform");
	cls.wait_console = cmd.has_argument("wait-console");
	cls.do_compile = cmd.has_argument("compile");
	cls.do_continue = cmd.has_argument("continue");

	cls.platform = cmd.get_parameter("platform");
	if (cls.do_compile && !cls.platform)
	{
		help("Platform must be specified.");
		exit(EXIT_FAILURE);
	}

	const char* parent = cmd.get_parameter("parent-window");
	if (parent)
	{
		cls.parent_window = string::parse_uint(parent);
	}

	return cls;
}

ConfigSettings parse_config_file(Filesystem& fs)
{
	ConfigSettings cs;
	cs.console_port = 10001;
	cs.boot_package = 0;
	cs.boot_script = 0;
	cs.window_width = CROWN_DEFAULT_WINDOW_WIDTH;
	cs.window_height = CROWN_DEFAULT_WINDOW_HEIGHT;

	File* tmpfile = fs.open("crown.config", FOM_READ);
	JSONParser config(*tmpfile);
	fs.close(tmpfile);
	JSONElement root = config.root();

	JSONElement cport = root.key_or_nil("console_port");
	if (!cport.is_nil())
	{
		cs.console_port = (int16_t) cport.to_int();
	}

	JSONElement window_width = root.key_or_nil("window_width");
	if (!window_width.is_nil())
	{
		cs.window_width = math::max((uint16_t)1, (uint16_t)window_width.to_int());
	}

	JSONElement window_height = root.key_or_nil("window_height");
	if (!window_height.is_nil())
	{
		cs.window_height = math::max((uint16_t)1, (uint16_t)window_height.to_int());
	}

	cs.boot_script = root.key("boot_script").to_resource_id("lua").name;
	cs.boot_package = root.key("boot_package").to_resource_id("package").name;

	return cs;
}

bool init(Filesystem& fs, const ConfigSettings& cs)
{
	input_globals::init();
	audio_globals::init();
	physics_globals::init();
	bgfx::init();
	device_globals::init(fs, cs.boot_package, cs.boot_script);
	device()->init();
	return true;
}

void update()
{
	while (!process_events() && device()->is_running())
	{
#if defined(CROWN_DEBUG)
		console_server_globals::console().update();
#endif
		device()->update();
		input_globals::keyboard().update();
		input_globals::mouse().update();
		input_globals::touch().update();
	}
}

void shutdown()
{
	device()->shutdown();
	device_globals::shutdown();
	bgfx::shutdown();
	physics_globals::shutdown();
	audio_globals::shutdown();
	input_globals::shutdown();
}
} // namespace crown
<|endoftext|>


<commit_before>// Standard includes
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <cmath>
#include <string.h>
#include <inttypes.h>
#include <fstream>

// Serial includes
#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#
#ifdef __linux
#include <sys/ioctl.h>
#endif

#include "serialwifly.h" 	// this is from Louis' wifly code, which will be a library
#include "common.h"
#include "wifly_thread.h"
#include "test.h" 			// for bearing calculation
#include "commander.h"

using std::string;
using std::vector;
using namespace std;

/* this is to help with some of the rotation logic */
bool in_rotation = false;

/* keep track of the previous hunt state, as hunt state is sent periodically, not just on updates */
uint8_t prev_hunt_state = 10;

/* whether or not we are currently rotating */
bool rotating = false;

/* whether or not we are currently moving */
bool moving = false;

int wifly_connect(char *port) {

	/* Start the connection to the WiFly */
	/* If the connection does not exist, quit */
	/* This is assuming we want to connect to /dev/ttyUSB0 */
	/* TODO: Don't make that assumption */
	int fd = start_connection(port);
	if (fd < 0)
	{
		// TODO: figure out what we do want to return when there is an error
		printf("Error connecting to wifly. Exiting...\n");
		return 0;
	}

	return fd;
}

void update_state(uint8_t &new_state) {

	switch (new_state) {
	case TRACKING_HUNT_STATE_ROTATE:
		rotating = true;
		break;
	case TRACKING_HUNT_STATE_MOVE:
		moving = true;
		break;
	case TRACKING_HUNT_STATE_OFF:
		// finished = true;
		break;
	case TRACKING_HUNT_STATE_START:
		// starting = true;
		break;
	}
}

void *wifly_thread(void *param) {

	// retrieve the MAVInfo struct that is sent to this function as a parameter
	struct MAVInfo *uavData = (struct MAVInfo *)param;

	// some constants that all need to become parameters
	int num_samples = 1;
	char *ssid = (char *) "JAMMER01";
	char *file_name = (char *) "wifly.csv";
	char *bearing_file_name = (char *) "bearing_calc.csv";
	char *port = (char *) "/dev/ttyUSB0";

	// connect to the wifly
	int wifly_fd = wifly_connect(port);

	if (wifly_fd < 0) {
		printf("Error opening wifly connection\n");
		return NULL;
	}

	/* Go into command mode */
	commandmode(wifly_fd);

	/* Open a file to write values to */
	/* Appending values */
	FILE *wifly_file = fopen(file_name, "a");
	if (wifly_file == NULL)
	{
		// TODO: figure out what we do want to return when there is an error
		printf("Error opening wifly output file\n");
		return NULL;
	}

	/* Open a file to write bearing calcs to */
	FILE *bearing_file = fopen(bearing_file_name, "a");
	if (bearing_file == NULL)
	{
		// TODO: figure out what we do want to return when there is an error
		printf("Error opening bearing output file\n");
		return NULL;
	}

	if (get_commands) {
		load_move_commands();
	}

	vector<double> angles;
	vector<double> gains;

	// main loop that should be constantly taking measurements
	// until the main program is stopped
	while (RUNNING_FLAG) {

		// handle hunt state changes required (sending of commands)
		if (uavData->tracking_status.hunt_mode_state != prev_hunt_state) {

			printf("State changed from %u to %u\n", prev_hunt_state, uavData->tracking_status.hunt_mode_state);

			if (uavData->tracking_status.hunt_mode_state == TRACKING_HUNT_STATE_WAIT) {
				send_next_command(prev_hunt_state, uavData->tracking_status.hunt_mode_state);

				// TODO: maybe want to update the state immediately here...
			} else {
				update_state(uavData->tracking_status.hunt_mode_state);
			}

			// update the prev hunt state to be this new state
			prev_hunt_state = uavData->tracking_status.hunt_mode_state;
			printf("Prev State changed to: %u\n", prev_hunt_state);
		}

		// make measurements (depending on the current state)

		/* check if we are in an official rotation */
		if (rotating) {
			if (!in_rotation) {
				// set our logic to mark we are now running the rotation logic
				in_rotation = true;

				// clear the vectors
				angles.clear();
				gains.clear();
			}

			angles.push_back((double) uavData->vfr_hud.heading);
			gains.push_back(scanrssi(wifly_fd, ssid));

		}

		if (!rotating && in_rotation) {
			in_rotation = false;

			// do bearing calculation at this point
			double bearing = get_bearing(angles, gains);

			// write the lat, lon, alt and bearing to file
			fprintf(bearing_file, "%llu, %i,%i,%f,%f\n", uavData->sys_time_us.time_unix_usec, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt, bearing);

			// send a mavlink message of the calculated bearing
			send_bearing_message(bearing, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt);

			// tell pixhawk we are finished with the rotation
			// send_finish_command();
		}

		/* Scan values to this file */
		/* Add degree at which you measure first */
		// cout << uavData->vfr_hud.heading << " ";
		fprintf(wifly_file, "%llu,%u,%i,%i,%i,%f,", uavData->sys_time_us.time_unix_usec, uavData->custom_mode, uavData->vfr_hud.heading, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt);
		int rssi = scanrssi_f(wifly_fd, ssid, wifly_file, num_samples);

		cout << uavData->vfr_hud.heading << " " << rssi << "\n";

		// send a mavlink message with the current rssi
		send_rssi_message(rssi, uavData->vfr_hud.heading, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt);

		// TODO: send mavlink message of calculated rssi...

		// send a message with a rotate command for testing purposes at the moment
		// sendRotateCommand(-1.0);

		/* sleep for some time before making another measurement (30 ms for now) */
		usleep(30000);

	}

	/* Be sure to close the output file and connection */
	fclose(wifly_file);
	close(wifly_fd);

	return NULL;
}
<commit_msg>make the loop time pause dynamic, to ensure measurements happen every 30ms regardless of runtime of the rest of the stuff<commit_after>// Standard includes
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <cmath>
#include <string.h>
#include <inttypes.h>
#include <fstream>
#include <time.h>

// Serial includes
#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#
#ifdef __linux
#include <sys/ioctl.h>
#endif

#include "serialwifly.h" 	// this is from Louis' wifly code, which will be a library
#include "common.h"
#include "wifly_thread.h"
#include "test.h" 			// for bearing calculation
#include "commander.h"

using std::string;
using std::vector;
using namespace std;

/* this is to help with some of the rotation logic */
bool in_rotation = false;

/* keep track of the previous hunt state, as hunt state is sent periodically, not just on updates */
uint8_t prev_hunt_state = 10;

/* whether or not we are currently rotating */
bool rotating = false;

/* whether or not we are currently moving */
bool moving = false;

/* microsecond timestamp of the previous loop iteration */
unsigned long prev_loop_timestamp = 0;

int wifly_connect(char *port) {

	/* Start the connection to the WiFly */
	/* If the connection does not exist, quit */
	/* This is assuming we want to connect to /dev/ttyUSB0 */
	/* TODO: Don't make that assumption */
	int fd = start_connection(port);
	if (fd < 0)
	{
		// TODO: figure out what we do want to return when there is an error
		printf("Error connecting to wifly. Exiting...\n");
		return 0;
	}

	return fd;
}

void update_state(uint8_t &new_state) {

	switch (new_state) {
	case TRACKING_HUNT_STATE_ROTATE:
		rotating = true;
		break;
	case TRACKING_HUNT_STATE_MOVE:
		moving = true;
		break;
	case TRACKING_HUNT_STATE_OFF:
		// finished = true;
		break;
	case TRACKING_HUNT_STATE_START:
		// starting = true;
		break;
	}
}

void *wifly_thread(void *param) {

	// retrieve the MAVInfo struct that is sent to this function as a parameter
	struct MAVInfo *uavData = (struct MAVInfo *)param;

	// some constants that all need to become parameters
	int num_samples = 1;
	char *ssid = (char *) "JAMMER01";
	char *file_name = (char *) "wifly.csv";
	char *bearing_file_name = (char *) "bearing_calc.csv";
	char *port = (char *) "/dev/ttyUSB0";

	// connect to the wifly
	int wifly_fd = wifly_connect(port);

	if (wifly_fd < 0) {
		printf("Error opening wifly connection\n");
		return NULL;
	}

	/* Go into command mode */
	commandmode(wifly_fd);

	/* Open a file to write values to */
	/* Appending values */
	FILE *wifly_file = fopen(file_name, "a");
	if (wifly_file == NULL)
	{
		// TODO: figure out what we do want to return when there is an error
		printf("Error opening wifly output file\n");
		return NULL;
	}

	/* Open a file to write bearing calcs to */
	FILE *bearing_file = fopen(bearing_file_name, "a");
	if (bearing_file == NULL)
	{
		// TODO: figure out what we do want to return when there is an error
		printf("Error opening bearing output file\n");
		return NULL;
	}

	if (get_commands) {
		load_move_commands();
	}

	vector<double> angles;
	vector<double> gains;

	struct timeval tv;

	// main loop that should be constantly taking measurements
	// until the main program is stopped
	while (RUNNING_FLAG) {

		// only want to execute this at most ever 30 ms
		// basically does a dynamic sleep in the sense that if there is a lot of processing time for doing the bearing
		// calculation, we will only pause as long as required so measurements are really made every 30 ms
		// (unless of course bearing calculations take too long)
		gettimeofday(&tv, NULL);
		unsigned long current_loop_time = 1000000 * tv_sec + tv_usec;
		if (prev_loop_timestamp != 0 && (current_loop_time - prev_loop_timestamp) < 30000) {
			continue;
		}
		prev_loop_timestamp = current_loop_time;

		// handle hunt state changes required (sending of commands)
		if (uavData->tracking_status.hunt_mode_state != prev_hunt_state) {

			printf("State changed from %u to %u\n", prev_hunt_state, uavData->tracking_status.hunt_mode_state);

			if (uavData->tracking_status.hunt_mode_state == TRACKING_HUNT_STATE_WAIT) {
				send_next_command(prev_hunt_state, uavData->tracking_status.hunt_mode_state);

				// TODO: maybe want to update the state immediately here...
			} else {
				update_state(uavData->tracking_status.hunt_mode_state);
			}

			// update the prev hunt state to be this new state
			prev_hunt_state = uavData->tracking_status.hunt_mode_state;
			printf("Prev State changed to: %u\n", prev_hunt_state);
		}

		// make measurements (depending on the current state)

		/* check if we are in an official rotation */
		if (rotating) {
			if (!in_rotation) {
				// set our logic to mark we are now running the rotation logic
				in_rotation = true;

				// clear the vectors
				angles.clear();
				gains.clear();
			}

			angles.push_back((double) uavData->vfr_hud.heading);
			gains.push_back(scanrssi(wifly_fd, ssid));

		}

		if (!rotating && in_rotation) {
			in_rotation = false;

			// do bearing calculation at this point
			double bearing = get_bearing(angles, gains);

			// write the lat, lon, alt and bearing to file
			fprintf(bearing_file, "%llu, %i,%i,%f,%f\n", uavData->sys_time_us.time_unix_usec, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt, bearing);

			// send a mavlink message of the calculated bearing
			send_bearing_message(bearing, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt);

			// tell pixhawk we are finished with the rotation
			// send_finish_command();
		}

		/* Scan values to this file */
		/* Add degree at which you measure first */
		// cout << uavData->vfr_hud.heading << " ";
		fprintf(wifly_file, "%llu,%u,%i,%i,%i,%f,", uavData->sys_time_us.time_unix_usec, uavData->custom_mode, uavData->vfr_hud.heading, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt);
		int rssi = scanrssi_f(wifly_fd, ssid, wifly_file, num_samples);

		cout << uavData->vfr_hud.heading << " " << rssi << "\n";

		// send a mavlink message with the current rssi
		send_rssi_message(rssi, uavData->vfr_hud.heading, uavData->gps_position.lat, uavData->gps_position.lon, uavData->vfr_hud.alt);

		// TODO: send mavlink message of calculated rssi...

		// send a message with a rotate command for testing purposes at the moment
		// sendRotateCommand(-1.0);

		/* sleep for some time before making another measurement (30 ms for now) */
		// usleep(30000);

	}

	/* Be sure to close the output file and connection */
	fclose(wifly_file);
	close(wifly_fd);

	return NULL;
}
<|endoftext|>