<commit_before>
#include <tilck/common/basic_defs.h>

#include <cstdio>
#include <cstdint>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <random>

#include <gtest/gtest.h>
#include "mocks.h"
#include "kernel_init_funcs.h"

extern "C" {
   #include <tilck/kernel/system_mmap.h>
   void append_mem_region(memory_region_t r);
   void fix_mem_regions(void);
   void align_mem_regions_to_page_boundary(void);
   void sort_mem_regions(void);
   void merge_adj_mem_regions(void);
   void handle_overlapping_regions(void);
}

void reset_mem_regions(void)
{
   memset(mem_regions, 0, sizeof(mem_regions));
   mem_regions_count = 0;
}

TEST(mem_regions, large_mem)
{
   reset_mem_regions();

   append_mem_region(memory_region_t{
      0x0,
      0x9dc00 - 0x0,
      1,
      0
   });

   append_mem_region(memory_region_t{
      0x9dc00,
      0xa0000 - 0x9dc00,
      2,
      0
   });

   append_mem_region(memory_region_t{
      0xe0000,
      0x100000 - 0xe0000,
      2,
      0
   });

   append_mem_region(memory_region_t{
      0x100000000,
      0x47e800000 - 0x100000000,
      1,
      0
   });

   dump_memory_map("Original memory map", mem_regions, mem_regions_count);

   //fix_mem_regions();

   align_mem_regions_to_page_boundary();
   sort_mem_regions();
   merge_adj_mem_regions();
   handle_overlapping_regions();

   dump_memory_map("Normalized memory map", mem_regions, mem_regions_count);
}
<commit_msg>[system_mmap][gtests] Cosmetic improvements to the test<commit_after>
#include <tilck/common/basic_defs.h>

#include <cstdio>
#include <cstdint>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <random>

#include <gtest/gtest.h>
#include "mocks.h"
#include "kernel_init_funcs.h"

extern "C" {
   #include <tilck/kernel/system_mmap.h>
   void append_mem_region(memory_region_t r);
   void fix_mem_regions(void);
   void align_mem_regions_to_page_boundary(void);
   void sort_mem_regions(void);
   void merge_adj_mem_regions(void);
   void handle_overlapping_regions(void);
}

class mem_reg2 {

   public:

   u64 start;
   u64 end;
   u32 type;
   u32 extra;

   operator memory_region_t() {
      return memory_region_t{start, end - start, type, extra};
   }
};

void reset_mem_regions(void)
{
   memset(mem_regions, 0, sizeof(mem_regions));
   mem_regions_count = 0;
}

TEST(mem_regions, large_mem)
{
   reset_mem_regions();

   append_mem_region(mem_reg2{0x00000, 0x9dc00, 1, 0});
   append_mem_region(mem_reg2{0x9dc00, 0xa0000, 2, 0});
   append_mem_region(mem_reg2{0xe0000, 0x100000, 2, 0});
   append_mem_region(mem_reg2{0x100000000ull, 0x47e800000ull, 1, 0});

   dump_memory_map("Original memory map", mem_regions, mem_regions_count);

   //fix_mem_regions();

   align_mem_regions_to_page_boundary();
   sort_mem_regions();
   merge_adj_mem_regions();
   handle_overlapping_regions();

   dump_memory_map("Normalized memory map", mem_regions, mem_regions_count);
}
<|endoftext|>


<commit_before>#include <cmath>
#include <cstdlib>
#include <fstream>
#include <vector>
#include "args.h"
#include "kernel.h"
#include "namespace.h"
#include "tree.h"
#include "verify.h"

#define CHECK_MONOPOLE

using namespace EXAFMM_NAMESPACE;

int main(int argc, char ** argv) {
  const int N = 10000;
  int level = 4;
  int nx = 1 << level;          // number of leafs in each dimension
  int nleaf = nx * nx * nx;     // number of leafs if full
  int i, l, d;                  // iterator in loops

  Targets targets(N);
  Sources sources(N);
  std::vector<int> targetKeys(N), sourceKeys(N);
  ivec3 iX, jX;

  // generate rand X and key for targets and sources
  for (i=0; i<N; i++) {
    for (d=0; d<3; d++) {
      targets[i].X[d] = drand48();
      sources[i].X[d] = drand48();
      iX[d] = (int) (targets[i].X[d] * nx);
      jX[d] = (int) (sources[i].X[d] * nx);
    }
    targets[i].F = 0;
    sources[i].Q = 1.0/N;
    targetKeys[i] = getKey(iX, level);
    sourceKeys[i] = getKey(jX, level);
  }

  // sort targets and sources based on Morton keys
  std::vector<int> targetPermutation(N), sourcePermutation(N);
  sortKey(targetKeys, targetPermutation);
  sortKey(sourceKeys, sourcePermutation);

  // permutate targets, sources and keys
  permutate<Targets>(targets, targetPermutation);
  permutate<Sources>(sources, sourcePermutation);
  permutate< std::vector<int> >(targetKeys, targetPermutation);
  permutate< std::vector<int> >(sourceKeys, sourcePermutation);

#if 0
  for (i=0; i<N; i++) {
    std::cout << i << " " << targetKeys[i] << " " << targets[i].X << std::endl;
    std::cout << i << " " << sourceKeys[i] << " " << sources[i].X << std::endl;
  }
#endif

  // calculate offset vectors for adaptive tree
  std::vector<int> targetNonEmpty(level+1, 0), sourceNonEmpty(level+1, 0);  // num of non-empty cells at each level
  std::vector<int> targetOffset(nleaf), sourceOffset(nleaf);  // leaf morton key -> particle index offset
  std::vector< std::vector<int> > targetIndex2Key( level+1,    // index2Key[level][index] -> Morton key
                                                   std::vector<int>(nleaf, 0) );
  std::vector< std::vector<int> > sourceIndex2Key( level+1,
                                                   std::vector<int>(nleaf, 0) );
  std::vector< std::vector<int> > targetKey2Index( level+1,    // key2Index[level][key] -> index at non-empty cells' list
                                                   std::vector<int>(nleaf, 0) );
  std::vector< std::vector<int> > sourceKey2Index( level+1,
                                                   std::vector<int>(nleaf, 0) );

  // leaf level
  int key = -1;
  for (i=0; i<N; i++) {              // i: current particle index
    if (key != targetKeys[i]) {      // if previous key != current key (found a new nonempty cell)
      key = targetKeys[i];           // store the current key
      targetIndex2Key[level][targetNonEmpty[level]] = key;   // map nonempty counter -> new key
      targetKey2Index[level][key] = targetNonEmpty[level];   // map new key -> nonempty counter
      targetOffset[targetNonEmpty[level]] = i;               // record the first target index of this new cell
      targetNonEmpty[level]++;       // increase the counter of nonempty cells at leaf level
    }
  }
  targetOffset[targetNonEmpty[level]] = N;                   // for the last leaf cell

  key = -1;
  for (i=0; i<N; i++) {              // i: current particle index
    if (key != sourceKeys[i]) {      // if previous key != current key (found a new nonempty cell)
      key = sourceKeys[i];           // store the current key
      sourceIndex2Key[level][sourceNonEmpty[level]] = key;   // map nonempty counter -> new key
      sourceKey2Index[level][key] = sourceNonEmpty[level];   // map new key -> nonempty counter
      sourceOffset[sourceNonEmpty[level]] = i;               // record the first target index of this new cell
      sourceNonEmpty[level]++;       // increase the counter of nonempty cells at leaf level
    }
  }
  sourceOffset[sourceNonEmpty[level]] = N;                   // for the last leaf cell

  // non-leaf level
  for (l=level; l>0; l--) {          // l: current level, l-1: parent level
    key = -1;                        // reset key
    for (i=0; i<targetNonEmpty[l]; i++) {                  // i: nonempty cell at level l
      if (key != targetIndex2Key[l][i]/8) {                // if previous key != i's parent key
        key = targetIndex2Key[l][i]/8;                     // store i's parent key
        targetIndex2Key[l-1][targetNonEmpty[l-1]] = key;   // map nonempty counter -> new parent key
        targetKey2Index[l-1][key] = targetNonEmpty[l-1];   // map new parent key -> nonempty counter
        targetNonEmpty[l-1]++;                             //
      }
    }
  }
  for (l=level; l>0; l--) {          // l: current level, l-1: parent level
    key = -1;                        // reset key
    for (i=0; i<sourceNonEmpty[l]; i++) {                  // i: nonempty cell at level l
      if (key != sourceIndex2Key[l][i]/8) {                // if previous key != i's parent key
        key = sourceIndex2Key[l][i]/8;                     // store i's parent key
        sourceIndex2Key[l-1][sourceNonEmpty[l-1]] = key;   // map nonempty counter -> new parent key
        sourceKey2Index[l-1][key] = sourceNonEmpty[l-1];   // map new parent key -> nonempty counter
        sourceNonEmpty[l-1]++;                             //
      }
    }
  }

  // level offset
  std::vector<int> targetLevelOffset(level+1, 0), sourceLevelOffset(level+1, 0);
  for (l=0; l<level; l++) {
    targetLevelOffset[l+1] = targetLevelOffset[l] + targetNonEmpty[l];
    sourceLevelOffset[l+1] = sourceLevelOffset[l] + sourceNonEmpty[l];
  }

#if 0
  for (l=0; l<level+1; l++) std::cout << targetNonEmpty[l] << " "
                                      << targetLevelOffset[l] << std::endl;
  for (l=0; l<level+1; l++) std::cout << sourceNonEmpty[l] << " "
                                      << sourceLevelOffset[l] << std::endl;
#endif

  std::vector<real_t> M(sourceNonEmpty[level]+sourceLevelOffset[level], 0.0);
  std::vector<real_t> L(targetNonEmpty[level]+targetLevelOffset[level], 0.0);

  // P2M
  int j;
   for (i=0; i<sourceNonEmpty[level]; i++) {              // i: nonempty source cell index
    for (j=sourceOffset[i]; j<sourceOffset[i+1]; j++) {   // j: source index
      M[i+sourceLevelOffset[level]] += sources[j].Q;
    }
  }

  // M2M
  for (l=level; l>0; l--) {                 // l: current level
    for (i=0; i<sourceNonEmpty[l]; i++) {   // i: nonempty source cell index in level l
      key = sourceIndex2Key[l][i];          // key: i's Morton key
      M[sourceKey2Index[l-1][key/8]+sourceLevelOffset[l-1]] += M[i+sourceLevelOffset[l]];
    }
  }

  // check monopole of root
#ifdef CHECK_MONOPOLE
  std::cout << "monopole of root: " << M[0] << std::endl;
  return 0;
#endif

  // M2L
  int count=0;
  for (l=2; l<=level; l++) {                // l: current level
    nx = 1 << l;                            // nx: number of cells in one-axis in level l
    for (i=0; i<targetNonEmpty[l]; i++) {   // i: nonempty target cell index in level l
      getIX(iX, targetIndex2Key[l][i]);     // i -> key -> iX
      for (j=0; j<sourceNonEmpty[l]; j++) { // j: nonempty source cell index in level l
        getIX(jX, sourceIndex2Key[l][j]);   // j -> key -> jX
        if (isNeighbor(iX/2, jX/2)) {       // if i,j's parents are neighbor
          if (!isNeighbor(iX, jX)) {        // and i,j are non-neighbor
            count++;
            real_t dx = (real_t) (iX[0] - jX[0]) / nx;
            real_t dy = (real_t) (iX[1] - jX[1]) / nx;
            real_t dz = (real_t) (iX[2] - jX[2]) / nx;
            real_t r = std::sqrt(dx*dx + dy*dy + dz*dz);
            L[i+targetLevelOffset[l]] += M[j+sourceLevelOffset[l]] / r;
          }
        }
      }
    }
  }

  // L2L
  for (l=3; l<=level; l++) {                // l: current level
    for (i=0; i<targetNonEmpty[l]; i++) {   // i: nonempty target cell index in level l
      key = targetIndex2Key[l][i];          // key: i's Morton key
      L[i+targetLevelOffset[l]] += L[targetKey2Index[l-1][key/8]+targetLevelOffset[l-1]];
    }
  }

  // L2P
  for (i=0; i<targetNonEmpty[level]; i++) {
    for (j=targetOffset[i]; j<targetOffset[i+1]; j++) {
      targets[j].F += L[i+targetLevelOffset[level]];
    }
  }

  // P2P
  for (int ic=0; ic<targetNonEmpty[level]; ic++) {
    getIX(iX, targetIndex2Key[level][ic]);
    for (int jc=0; jc<sourceNonEmpty[level]; jc++) {
      getIX(jX, sourceIndex2Key[level][jc]);
      if (isNeighbor(iX, jX)) {
        for (i=targetOffset[ic]; i<targetOffset[ic+1]; i++) {
          for (j=sourceOffset[jc]; j<sourceOffset[jc+1]; j++) {
          vec3 dX = targets[i].X - sources[j].X;
          real_t r = std::sqrt(norm(dX));
          if (r!=0) targets[i].F += sources[j].Q / r;
          }
        }
      }
    }
  }

#ifdef PRINT_RESULT
  // check answer
  for (i=0; i<N; i++) {
    real_t Fi = 0;
    for (j=0; j<N; j++) {
      vec3 dX = targets[i].X - sources[j].X;
      real_t r = std::sqrt(norm(dX));
      if (r!=0) Fi += sources[j].Q / r;
    }
    std::cout << i << " " << targets[i].F << " " << Fi << std::endl;
  }
#endif
}
<commit_msg>remove unused headers<commit_after>#include <cmath>
#include <cstdlib>
#include <fstream>
#include <vector>
#include "args.h"
#include "namespace.h"
#include "tree.h"

#define CHECK_MONOPOLE

using namespace EXAFMM_NAMESPACE;

int main(int argc, char ** argv) {
  const int N = 10000;
  int level = 4;
  int nx = 1 << level;          // number of leafs in each dimension
  int nleaf = nx * nx * nx;     // number of leafs if full
  int i, l, d;                  // iterator in loops

  Targets targets(N);
  Sources sources(N);
  std::vector<int> targetKeys(N), sourceKeys(N);
  ivec3 iX, jX;

  // generate rand X and key for targets and sources
  for (i=0; i<N; i++) {
    for (d=0; d<3; d++) {
      targets[i].X[d] = drand48();
      sources[i].X[d] = drand48();
      iX[d] = (int) (targets[i].X[d] * nx);
      jX[d] = (int) (sources[i].X[d] * nx);
    }
    targets[i].F = 0;
    sources[i].Q = 1.0/N;
    targetKeys[i] = getKey(iX, level);
    sourceKeys[i] = getKey(jX, level);
  }

  // sort targets and sources based on Morton keys
  std::vector<int> targetPermutation(N), sourcePermutation(N);
  sortKey(targetKeys, targetPermutation);
  sortKey(sourceKeys, sourcePermutation);

  // permutate targets, sources and keys
  permutate<Targets>(targets, targetPermutation);
  permutate<Sources>(sources, sourcePermutation);
  permutate< std::vector<int> >(targetKeys, targetPermutation);
  permutate< std::vector<int> >(sourceKeys, sourcePermutation);

#if 0
  for (i=0; i<N; i++) {
    std::cout << i << " " << targetKeys[i] << " " << targets[i].X << std::endl;
    std::cout << i << " " << sourceKeys[i] << " " << sources[i].X << std::endl;
  }
#endif

  // calculate offset vectors for adaptive tree
  std::vector<int> targetNonEmpty(level+1, 0), sourceNonEmpty(level+1, 0);  // num of non-empty cells at each level
  std::vector<int> targetOffset(nleaf), sourceOffset(nleaf);  // leaf morton key -> particle index offset
  std::vector< std::vector<int> > targetIndex2Key( level+1,    // index2Key[level][index] -> Morton key
                                                   std::vector<int>(nleaf, 0) );
  std::vector< std::vector<int> > sourceIndex2Key( level+1,
                                                   std::vector<int>(nleaf, 0) );
  std::vector< std::vector<int> > targetKey2Index( level+1,    // key2Index[level][key] -> index at non-empty cells' list
                                                   std::vector<int>(nleaf, 0) );
  std::vector< std::vector<int> > sourceKey2Index( level+1,
                                                   std::vector<int>(nleaf, 0) );

  // leaf level
  int key = -1;
  for (i=0; i<N; i++) {              // i: current particle index
    if (key != targetKeys[i]) {      // if previous key != current key (found a new nonempty cell)
      key = targetKeys[i];           // store the current key
      targetIndex2Key[level][targetNonEmpty[level]] = key;   // map nonempty counter -> new key
      targetKey2Index[level][key] = targetNonEmpty[level];   // map new key -> nonempty counter
      targetOffset[targetNonEmpty[level]] = i;               // record the first target index of this new cell
      targetNonEmpty[level]++;       // increase the counter of nonempty cells at leaf level
    }
  }
  targetOffset[targetNonEmpty[level]] = N;                   // for the last leaf cell

  key = -1;
  for (i=0; i<N; i++) {              // i: current particle index
    if (key != sourceKeys[i]) {      // if previous key != current key (found a new nonempty cell)
      key = sourceKeys[i];           // store the current key
      sourceIndex2Key[level][sourceNonEmpty[level]] = key;   // map nonempty counter -> new key
      sourceKey2Index[level][key] = sourceNonEmpty[level];   // map new key -> nonempty counter
      sourceOffset[sourceNonEmpty[level]] = i;               // record the first target index of this new cell
      sourceNonEmpty[level]++;       // increase the counter of nonempty cells at leaf level
    }
  }
  sourceOffset[sourceNonEmpty[level]] = N;                   // for the last leaf cell

  // non-leaf level
  for (l=level; l>0; l--) {          // l: current level, l-1: parent level
    key = -1;                        // reset key
    for (i=0; i<targetNonEmpty[l]; i++) {                  // i: nonempty cell at level l
      if (key != targetIndex2Key[l][i]/8) {                // if previous key != i's parent key
        key = targetIndex2Key[l][i]/8;                     // store i's parent key
        targetIndex2Key[l-1][targetNonEmpty[l-1]] = key;   // map nonempty counter -> new parent key
        targetKey2Index[l-1][key] = targetNonEmpty[l-1];   // map new parent key -> nonempty counter
        targetNonEmpty[l-1]++;                             //
      }
    }
  }
  for (l=level; l>0; l--) {          // l: current level, l-1: parent level
    key = -1;                        // reset key
    for (i=0; i<sourceNonEmpty[l]; i++) {                  // i: nonempty cell at level l
      if (key != sourceIndex2Key[l][i]/8) {                // if previous key != i's parent key
        key = sourceIndex2Key[l][i]/8;                     // store i's parent key
        sourceIndex2Key[l-1][sourceNonEmpty[l-1]] = key;   // map nonempty counter -> new parent key
        sourceKey2Index[l-1][key] = sourceNonEmpty[l-1];   // map new parent key -> nonempty counter
        sourceNonEmpty[l-1]++;                             //
      }
    }
  }

  // level offset
  std::vector<int> targetLevelOffset(level+1, 0), sourceLevelOffset(level+1, 0);
  for (l=0; l<level; l++) {
    targetLevelOffset[l+1] = targetLevelOffset[l] + targetNonEmpty[l];
    sourceLevelOffset[l+1] = sourceLevelOffset[l] + sourceNonEmpty[l];
  }

#if 0
  for (l=0; l<level+1; l++) std::cout << targetNonEmpty[l] << " "
                                      << targetLevelOffset[l] << std::endl;
  for (l=0; l<level+1; l++) std::cout << sourceNonEmpty[l] << " "
                                      << sourceLevelOffset[l] << std::endl;
#endif

  std::vector<real_t> M(sourceNonEmpty[level]+sourceLevelOffset[level], 0.0);
  std::vector<real_t> L(targetNonEmpty[level]+targetLevelOffset[level], 0.0);

  // P2M
  int j;
   for (i=0; i<sourceNonEmpty[level]; i++) {              // i: nonempty source cell index
    for (j=sourceOffset[i]; j<sourceOffset[i+1]; j++) {   // j: source index
      M[i+sourceLevelOffset[level]] += sources[j].Q;
    }
  }

  // M2M
  for (l=level; l>0; l--) {                 // l: current level
    for (i=0; i<sourceNonEmpty[l]; i++) {   // i: nonempty source cell index in level l
      key = sourceIndex2Key[l][i];          // key: i's Morton key
      M[sourceKey2Index[l-1][key/8]+sourceLevelOffset[l-1]] += M[i+sourceLevelOffset[l]];
    }
  }

  // check monopole of root
#ifdef CHECK_MONOPOLE
  std::cout << "monopole of root: " << M[0] << std::endl;
  return 0;
#endif

  // M2L
  int count=0;
  for (l=2; l<=level; l++) {                // l: current level
    nx = 1 << l;                            // nx: number of cells in one-axis in level l
    for (i=0; i<targetNonEmpty[l]; i++) {   // i: nonempty target cell index in level l
      getIX(iX, targetIndex2Key[l][i]);     // i -> key -> iX
      for (j=0; j<sourceNonEmpty[l]; j++) { // j: nonempty source cell index in level l
        getIX(jX, sourceIndex2Key[l][j]);   // j -> key -> jX
        if (isNeighbor(iX/2, jX/2)) {       // if i,j's parents are neighbor
          if (!isNeighbor(iX, jX)) {        // and i,j are non-neighbor
            count++;
            real_t dx = (real_t) (iX[0] - jX[0]) / nx;
            real_t dy = (real_t) (iX[1] - jX[1]) / nx;
            real_t dz = (real_t) (iX[2] - jX[2]) / nx;
            real_t r = std::sqrt(dx*dx + dy*dy + dz*dz);
            L[i+targetLevelOffset[l]] += M[j+sourceLevelOffset[l]] / r;
          }
        }
      }
    }
  }

  // L2L
  for (l=3; l<=level; l++) {                // l: current level
    for (i=0; i<targetNonEmpty[l]; i++) {   // i: nonempty target cell index in level l
      key = targetIndex2Key[l][i];          // key: i's Morton key
      L[i+targetLevelOffset[l]] += L[targetKey2Index[l-1][key/8]+targetLevelOffset[l-1]];
    }
  }

  // L2P
  for (i=0; i<targetNonEmpty[level]; i++) {
    for (j=targetOffset[i]; j<targetOffset[i+1]; j++) {
      targets[j].F += L[i+targetLevelOffset[level]];
    }
  }

  // P2P
  for (int ic=0; ic<targetNonEmpty[level]; ic++) {
    getIX(iX, targetIndex2Key[level][ic]);
    for (int jc=0; jc<sourceNonEmpty[level]; jc++) {
      getIX(jX, sourceIndex2Key[level][jc]);
      if (isNeighbor(iX, jX)) {
        for (i=targetOffset[ic]; i<targetOffset[ic+1]; i++) {
          for (j=sourceOffset[jc]; j<sourceOffset[jc+1]; j++) {
          vec3 dX = targets[i].X - sources[j].X;
          real_t r = std::sqrt(norm(dX));
          if (r!=0) targets[i].F += sources[j].Q / r;
          }
        }
      }
    }
  }

#ifdef PRINT_RESULT
  // check answer
  for (i=0; i<N; i++) {
    real_t Fi = 0;
    for (j=0; j<N; j++) {
      vec3 dX = targets[i].X - sources[j].X;
      real_t r = std::sqrt(norm(dX));
      if (r!=0) Fi += sources[j].Q / r;
    }
    std::cout << i << " " << targets[i].F << " " << Fi << std::endl;
  }
#endif
}
<|endoftext|>


<commit_before>// Copyright 2020 Global Phasing Ltd.

#include "common.h"
#include <pybind11/stl.h>
#include <pybind11/complex.h>
#include "gemmi/it92.hpp"
#include "gemmi/c4322.hpp"
#include "gemmi/sfcalc.hpp"   // for StructureFactorCalculator
#include "gemmi/dencalc.hpp"  // for DensityCalculator
#include "gemmi/fprime.hpp"   // for cromer_libermann_fprime_for_all_elements

namespace py = pybind11;
using gemmi::Element;

template<typename Table>
void add_sfcalc(py::module& m, const char* name, bool with_mb) {
  using SFC = gemmi::StructureFactorCalculator<Table>;
  py::class_<SFC> sfc(m, name);
  sfc
    .def(py::init<const gemmi::UnitCell&>())
    .def_readwrite("addends", &SFC::addends)
    .def("calculate_sf_from_model", &SFC::calculate_sf_from_model);
  if (with_mb)
    sfc
      .def("mott_bethe_factor", &SFC::mott_bethe_factor)
      .def("calculate_mb_z", &SFC::calculate_mb_z,
           py::arg("model"), py::arg("hkl"), py::arg("only_h")=false);
}

template<typename Table>
void add_dencalc(py::module& m, const char* name) {
  using DenCalc = gemmi::DensityCalculator<Table, float>;
  py::class_<DenCalc>(m, name)
    .def(py::init<>())
    .def_readonly("grid", &DenCalc::grid)
    .def_readwrite("d_min", &DenCalc::d_min)
    .def_readwrite("rate", &DenCalc::rate)
    .def_readwrite("blur", &DenCalc::blur)
    .def_readwrite("r_cut", &DenCalc::r_cut)
    .def_readwrite("addends", &DenCalc::addends)
    .def("set_refmac_compatible_blur", &DenCalc::set_refmac_compatible_blur)
    .def("put_model_density_on_grid", &DenCalc::put_model_density_on_grid)
    .def("initialize_grid", &DenCalc::initialize_grid)
    .def("add_model_density_to_grid", &DenCalc::add_model_density_to_grid)
    .def("add_c_contribution_to_grid", &DenCalc::add_c_contribution_to_grid)
    .def("set_grid_cell_and_spacegroup", &DenCalc::set_grid_cell_and_spacegroup)
    .def("reciprocal_space_multiplier", &DenCalc::reciprocal_space_multiplier)
    .def("mott_bethe_factor", &DenCalc::mott_bethe_factor)
    ;
}

void add_sf(py::module& m) {
  py::class_<gemmi::Addends>(m, "Addends")
    .def("set", &gemmi::Addends::set)
    .def("get", &gemmi::Addends::get)
    .def("clear", &gemmi::Addends::clear)
    .def("add_cl_fprime", [](gemmi::Addends& self, double energy) {
        gemmi::add_cl_fprime_for_all_elements(&self.values[1], energy);
    }, py::arg("energy"))
    .def("subtract_z", &gemmi::Addends::subtract_z,
         py::arg("except_hydrogen")=false)
    ;

  using IT92 = gemmi::IT92<double>;
  using C4322 = gemmi::C4322<double>;
  add_sfcalc<IT92>(m, "StructureFactorCalculatorX", true);
  add_sfcalc<C4322>(m, "StructureFactorCalculatorE", false);
  add_dencalc<IT92>(m, "DensityCalculatorX");
  add_dencalc<C4322>(m, "DensityCalculatorE");
}
<commit_msg>add a python binding<commit_after>// Copyright 2020 Global Phasing Ltd.

#include "common.h"
#include <pybind11/stl.h>
#include <pybind11/complex.h>
#include "gemmi/it92.hpp"
#include "gemmi/c4322.hpp"
#include "gemmi/sfcalc.hpp"   // for StructureFactorCalculator
#include "gemmi/dencalc.hpp"  // for DensityCalculator
#include "gemmi/fprime.hpp"   // for cromer_libermann_fprime_for_all_elements

namespace py = pybind11;
using gemmi::Element;

template<typename Table>
void add_sfcalc(py::module& m, const char* name, bool with_mb) {
  using SFC = gemmi::StructureFactorCalculator<Table>;
  py::class_<SFC> sfc(m, name);
  sfc
    .def(py::init<const gemmi::UnitCell&>())
    .def_readwrite("addends", &SFC::addends)
    .def("calculate_sf_from_model", &SFC::calculate_sf_from_model);
  if (with_mb)
    sfc
      .def("mott_bethe_factor", &SFC::mott_bethe_factor)
      .def("calculate_mb_z", &SFC::calculate_mb_z,
           py::arg("model"), py::arg("hkl"), py::arg("only_h")=false);
}

template<typename Table>
void add_dencalc(py::module& m, const char* name) {
  using DenCalc = gemmi::DensityCalculator<Table, float>;
  py::class_<DenCalc>(m, name)
    .def(py::init<>())
    .def_readonly("grid", &DenCalc::grid)
    .def_readwrite("d_min", &DenCalc::d_min)
    .def_readwrite("rate", &DenCalc::rate)
    .def_readwrite("blur", &DenCalc::blur)
    .def_readwrite("r_cut", &DenCalc::r_cut)
    .def_readwrite("addends", &DenCalc::addends)
    .def("set_refmac_compatible_blur", &DenCalc::set_refmac_compatible_blur)
    .def("put_model_density_on_grid", &DenCalc::put_model_density_on_grid)
    .def("initialize_grid", &DenCalc::initialize_grid)
    .def("add_model_density_to_grid", &DenCalc::add_model_density_to_grid)
    .def("add_atom_density_to_grid", &DenCalc::add_atom_density_to_grid)
    .def("add_c_contribution_to_grid", &DenCalc::add_c_contribution_to_grid)
    .def("set_grid_cell_and_spacegroup", &DenCalc::set_grid_cell_and_spacegroup)
    .def("reciprocal_space_multiplier", &DenCalc::reciprocal_space_multiplier)
    .def("mott_bethe_factor", &DenCalc::mott_bethe_factor)
    ;
}

void add_sf(py::module& m) {
  py::class_<gemmi::Addends>(m, "Addends")
    .def("set", &gemmi::Addends::set)
    .def("get", &gemmi::Addends::get)
    .def("clear", &gemmi::Addends::clear)
    .def("add_cl_fprime", [](gemmi::Addends& self, double energy) {
        gemmi::add_cl_fprime_for_all_elements(&self.values[1], energy);
    }, py::arg("energy"))
    .def("subtract_z", &gemmi::Addends::subtract_z,
         py::arg("except_hydrogen")=false)
    ;

  using IT92 = gemmi::IT92<double>;
  using C4322 = gemmi::C4322<double>;
  add_sfcalc<IT92>(m, "StructureFactorCalculatorX", true);
  add_sfcalc<C4322>(m, "StructureFactorCalculatorE", false);
  add_dencalc<IT92>(m, "DensityCalculatorX");
  add_dencalc<C4322>(m, "DensityCalculatorE");
}
<|endoftext|>


<commit_before>#include "CelestialBody.hpp"
#include "config.hpp"
#include "parametric_shapes.hpp"
#include "core/Bonobo.h"
#include "core/FPSCamera.h"
#include "core/helpers.hpp"
#include "core/node.hpp"
#include "core/ShaderProgramManager.hpp"

#include <imgui.h>

#include <clocale>
#include <cstdlib>

int main()
{
	std::setlocale(LC_ALL, "");

	using namespace std::literals::chrono_literals;

	//
	// Set up the framework
	//
	Bonobo framework;

	//
	// Set up the camera
	//
	InputHandler input_handler;
	FPSCameraf camera(0.5f * glm::half_pi<float>(),
	                  static_cast<float>(config::resolution_x) / static_cast<float>(config::resolution_y),
	                  0.01f, 1000.0f);
	camera.mWorld.SetTranslate(glm::vec3(0.0f, 0.0f, 6.0f));
	camera.mWorld.LookAt(glm::vec3(0.0f));
	camera.mMouseSensitivity = 0.003f;
	camera.mMovementSpeed = 3.0f; // 3 m/s => 10.8 km/h

	//
	// Create the window
	//
	WindowManager& window_manager = framework.GetWindowManager();
	WindowManager::WindowDatum window_datum{ input_handler, camera, config::resolution_x, config::resolution_y, 0, 0, 0, 0};
	GLFWwindow* window = window_manager.CreateGLFWWindow("EDAF80: Assignment 1", window_datum, config::msaa_rate);
	if (window == nullptr) {
		LogError("Failed to get a window: exiting.");

		return EXIT_FAILURE;
	}

	//
	// Load the sphere geometry
	//
	std::vector<bonobo::mesh_data> const objects = bonobo::loadObjects(config::resources_path("scenes/sphere.obj"));
	if (objects.empty()) {
		LogError("Failed to load the sphere geometry: exiting.");

		return EXIT_FAILURE;
	}
	bonobo::mesh_data const& sphere = objects.front();
	auto const saturn_ring_shape = parametric_shapes::createCircleRing(0.675f, 0.45f, 80u, 8u);

	//
	// Create the shader program
	//
	ShaderProgramManager program_manager;
	GLuint celestial_body_shader = 0u;
	program_manager.CreateAndRegisterProgram("Celestial Body",
	                                         { { ShaderType::vertex, "EDAF80/default.vert" },
	                                           { ShaderType::fragment, "EDAF80/default.frag" } },
	                                         celestial_body_shader);
	if (celestial_body_shader == 0u) {
		LogError("Failed to generate the “Celestial Body” shader program: exiting.");

		Log::View::Destroy();
		Log::Destroy();

		return EXIT_FAILURE;
	}
	GLuint celestial_ring_shader = 0u;
	program_manager.CreateAndRegisterProgram("Celestial Ring",
	                                         { { ShaderType::vertex, "EDAF80/celestial_ring.vert" },
	                                           { ShaderType::fragment, "EDAF80/celestial_ring.frag" } },
	                                         celestial_ring_shader);
	if (celestial_ring_shader == 0u) {
		LogError("Failed to generate the “Celestial Ring” shader program: exiting.");

		Log::View::Destroy();
		Log::Destroy();

		return EXIT_FAILURE;
	}

	//
	// Define all the celestial bodies constants.
	//
	glm::vec3 const sun_scale{ 1.0f };
	SpinConfiguration const sun_spin{ glm::radians(0.0f), glm::two_pi<float>() / 6.0f };

	glm::vec3 const mercury_scale{ 0.02f };
	SpinConfiguration const mercury_spin{ glm::radians(-0.0f), glm::two_pi<float>() / 180.0f };
	OrbitConfiguration const mercury_orbit{ 2.0f, glm::radians(-3.4f), glm::two_pi<float>() / 4.0f };

	glm::vec3 const venus_scale{ 0.05f };
	SpinConfiguration const venus_spin{ glm::radians(-2.6f), -glm::two_pi<float>() / 600.0f };
	OrbitConfiguration const venus_orbit{ 3.0f, glm::radians(-3.9f), glm::two_pi<float>() / 12.0f };

	glm::vec3 const earth_scale{ 0.05f };
	SpinConfiguration const earth_spin{ glm::radians(-23.0f), glm::two_pi<float>() / 3.0f };
	OrbitConfiguration const earth_orbit{ 4.0f, glm::radians(-7.2f), glm::two_pi<float>() / 20.0f };

	glm::vec3 const moon_scale{ 0.01f };
	SpinConfiguration const moon_spin{ glm::radians(-6.7f), glm::two_pi<float>() / 90.0f };
	OrbitConfiguration const moon_orbit{ 0.2f, glm::radians(29.0f), glm::two_pi<float>() / 1.3f };

	glm::vec3 const mars_scale{ 0.03f };
	SpinConfiguration const mars_spin{ glm::radians(-25.0f), glm::two_pi<float>() / 3.0f };
	OrbitConfiguration const mars_orbit{ 5.0f, glm::radians(-5.7f), glm::two_pi<float>() / 36.0f };

	glm::vec3 const jupiter_scale{ 0.5f };
	SpinConfiguration const jupiter_spin{ glm::radians(-3.1f), glm::two_pi<float>() / 1.0f };
	OrbitConfiguration const jupiter_orbit{ 13.0f, glm::radians(-6.1f), glm::two_pi<float>() / 220.0f };

	glm::vec3 const saturn_scale{ 0.4f };
	SpinConfiguration const saturn_spin{ glm::radians(-27.0f), glm::two_pi<float>() / 1.2f };
	OrbitConfiguration const saturn_orbit{ 16.0f, glm::radians(-5.5f), glm::two_pi<float>() / 400.0f };
	glm::vec2 const saturn_ring_scale{ 1.0f, 1.25f };

	glm::vec3 const uranus_scale{ 0.2f };
	SpinConfiguration const uranus_spin{ glm::radians(-82.0f), -glm::two_pi<float>() / 2.0f };
	OrbitConfiguration const uranus_orbit{ 18.0f, glm::radians(-6.5f), glm::two_pi<float>() / 1680.0f };

	glm::vec3 const neptune_scale{ 0.2f };
	SpinConfiguration const neptune_spin{ glm::radians(-28.0f), glm::two_pi<float>() / 2.0f };
	OrbitConfiguration const neptune_orbit{ 19.0f, glm::radians(-6.4f), glm::two_pi<float>() / 3200.0f };

	//
	// Load all textures.
	//
	GLuint const sun_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_sun.jpg"));
	GLuint const mercury_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_mercury.jpg"));
	GLuint const venus_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_venus_atmosphere.jpg"));
	GLuint const earth_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_earth_daymap.jpg"));
	GLuint const moon_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_moon.jpg"));
	GLuint const mars_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_mars.jpg"));
	GLuint const jupiter_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_jupiter.jpg"));
	GLuint const saturn_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_saturn.jpg"));
	GLuint const saturn_ring_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_saturn_ring_alpha.png"));
	GLuint const uranus_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_uranus.jpg"));
	GLuint const neptune_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_neptune.jpg"));

	//
	// Set up the celestial bodies.
	//
	CelestialBody moon(sphere, &celestial_body_shader, moon_texture);
	moon.set_scale(glm::vec3(0.3f));
	moon.set_spin(moon_spin);
	moon.set_orbit({1.5f, glm::radians(-66.0f), glm::two_pi<float>() / 1.3f});

	CelestialBody earth(sphere, &celestial_body_shader, earth_texture);
	earth.set_spin(earth_spin);
	earth.set_orbit({-2.5f, glm::radians(45.0f), glm::two_pi<float>() / 10.0f});
	earth.add_child(&moon);

	//
	// Define the colour and depth used for clearing.
	//
	glClearDepthf(1.0f);
	glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
	glEnable(GL_DEPTH_TEST);

	auto last_time = std::chrono::high_resolution_clock::now();

	bool pause_animation = false;
	bool show_logs = true;
	bool show_gui = true;
	float time_scale = 1.0f;

	while (!glfwWindowShouldClose(window)) {
		//
		// Compute timings information
		//
		auto const now_time = std::chrono::high_resolution_clock::now();
		auto const delta_time_us = std::chrono::duration_cast<std::chrono::microseconds>(now_time - last_time);
		auto const animation_delta_time_us = !pause_animation ? std::chrono::duration_cast<std::chrono::microseconds>(delta_time_us * time_scale) : 0us;
		last_time = now_time;

		//
		// Process inputs
		//
		glfwPollEvents();

		ImGuiIO const& io = ImGui::GetIO();
		input_handler.SetUICapture(io.WantCaptureMouse, io.WantCaptureKeyboard);
		input_handler.Advance();
		camera.Update(delta_time_us, input_handler);

		if (input_handler.GetKeycodeState(GLFW_KEY_F3) & JUST_RELEASED)
			show_logs = !show_logs;
		if (input_handler.GetKeycodeState(GLFW_KEY_F2) & JUST_RELEASED)
			show_gui = !show_gui;
		if (input_handler.GetKeycodeState(GLFW_KEY_F11) & JUST_RELEASED)
			window_manager.ToggleFullscreenStatusForWindow(window);

		// Retrieve the actual framebuffer size: for HiDPI monitors,
		// you might end up with a framebuffer larger than what you
		// actually asked for. For example, if you ask for a 1920x1080
		// framebuffer, you might get a 3840x2160 one instead.
		// Also it might change as the user drags the window between
		// monitors with different DPIs, or if the fullscreen status is
		// being toggled.
		int framebuffer_width, framebuffer_height;
		glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
		glViewport(0, 0, framebuffer_width, framebuffer_height);

		//
		// Start a new frame for Dear ImGui
		//
		window_manager.NewImGuiFrame();

		//
		// Clear the screen
		//
		glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

		//
		// Add controls to the scene.
		//
		bool const opened = ImGui::Begin("Scene controls", nullptr, ImGuiWindowFlags_None);
		if (opened)
		{
			ImGui::Checkbox("Pause the animation", &pause_animation);
			ImGui::SliderFloat("Time scale", &time_scale, 1e-1f, 10.0f);
		}
		ImGui::End();

		//
		// Traverse the scene graph and render all nodes
		//
		struct CelestialBodyRef
		{
			CelestialBody* body;
			glm::mat4 parent_transform;
		};
		// TODO: Replace this explicit rendering of the Earth and Moon
		// with a traversal of the scene graph and rendering of all its
		// nodes.
		earth.render(animation_delta_time_us, camera.GetWorldToClipMatrix(), glm::translate(glm::mat4(1.0f), glm::vec3(2.0f, 0.0f, 0.0f)));
		//moon.render(animation_delta_time_us, camera.GetWorldToClipMatrix());

		//
		// Display Dear ImGui windows
		//
		if (show_logs)
			Log::View::Render();
		window_manager.RenderImGuiFrame(show_gui);

		//
		// Queue the computed frame for display on screen
		//
		glfwSwapBuffers(window);
	}

	glDeleteTextures(1, &neptune_texture);
	glDeleteTextures(1, &uranus_texture);
	glDeleteTextures(1, &saturn_ring_texture);
	glDeleteTextures(1, &saturn_texture);
	glDeleteTextures(1, &jupiter_texture);
	glDeleteTextures(1, &mars_texture);
	glDeleteTextures(1, &moon_texture);
	glDeleteTextures(1, &earth_texture);
	glDeleteTextures(1, &venus_texture);
	glDeleteTextures(1, &mars_texture);
	glDeleteTextures(1, &sun_texture);

	return EXIT_SUCCESS;
}
<commit_msg>EDAF80/Lab1: Move GUI code around<commit_after>#include "CelestialBody.hpp"
#include "config.hpp"
#include "parametric_shapes.hpp"
#include "core/Bonobo.h"
#include "core/FPSCamera.h"
#include "core/helpers.hpp"
#include "core/node.hpp"
#include "core/ShaderProgramManager.hpp"

#include <imgui.h>

#include <clocale>
#include <cstdlib>

int main()
{
	std::setlocale(LC_ALL, "");

	using namespace std::literals::chrono_literals;

	//
	// Set up the framework
	//
	Bonobo framework;

	//
	// Set up the camera
	//
	InputHandler input_handler;
	FPSCameraf camera(0.5f * glm::half_pi<float>(),
	                  static_cast<float>(config::resolution_x) / static_cast<float>(config::resolution_y),
	                  0.01f, 1000.0f);
	camera.mWorld.SetTranslate(glm::vec3(0.0f, 0.0f, 6.0f));
	camera.mWorld.LookAt(glm::vec3(0.0f));
	camera.mMouseSensitivity = 0.003f;
	camera.mMovementSpeed = 3.0f; // 3 m/s => 10.8 km/h

	//
	// Create the window
	//
	WindowManager& window_manager = framework.GetWindowManager();
	WindowManager::WindowDatum window_datum{ input_handler, camera, config::resolution_x, config::resolution_y, 0, 0, 0, 0};
	GLFWwindow* window = window_manager.CreateGLFWWindow("EDAF80: Assignment 1", window_datum, config::msaa_rate);
	if (window == nullptr) {
		LogError("Failed to get a window: exiting.");

		return EXIT_FAILURE;
	}

	//
	// Load the sphere geometry
	//
	std::vector<bonobo::mesh_data> const objects = bonobo::loadObjects(config::resources_path("scenes/sphere.obj"));
	if (objects.empty()) {
		LogError("Failed to load the sphere geometry: exiting.");

		return EXIT_FAILURE;
	}
	bonobo::mesh_data const& sphere = objects.front();
	auto const saturn_ring_shape = parametric_shapes::createCircleRing(0.675f, 0.45f, 80u, 8u);

	//
	// Create the shader program
	//
	ShaderProgramManager program_manager;
	GLuint celestial_body_shader = 0u;
	program_manager.CreateAndRegisterProgram("Celestial Body",
	                                         { { ShaderType::vertex, "EDAF80/default.vert" },
	                                           { ShaderType::fragment, "EDAF80/default.frag" } },
	                                         celestial_body_shader);
	if (celestial_body_shader == 0u) {
		LogError("Failed to generate the “Celestial Body” shader program: exiting.");

		Log::View::Destroy();
		Log::Destroy();

		return EXIT_FAILURE;
	}
	GLuint celestial_ring_shader = 0u;
	program_manager.CreateAndRegisterProgram("Celestial Ring",
	                                         { { ShaderType::vertex, "EDAF80/celestial_ring.vert" },
	                                           { ShaderType::fragment, "EDAF80/celestial_ring.frag" } },
	                                         celestial_ring_shader);
	if (celestial_ring_shader == 0u) {
		LogError("Failed to generate the “Celestial Ring” shader program: exiting.");

		Log::View::Destroy();
		Log::Destroy();

		return EXIT_FAILURE;
	}

	//
	// Define all the celestial bodies constants.
	//
	glm::vec3 const sun_scale{ 1.0f };
	SpinConfiguration const sun_spin{ glm::radians(0.0f), glm::two_pi<float>() / 6.0f };

	glm::vec3 const mercury_scale{ 0.02f };
	SpinConfiguration const mercury_spin{ glm::radians(-0.0f), glm::two_pi<float>() / 180.0f };
	OrbitConfiguration const mercury_orbit{ 2.0f, glm::radians(-3.4f), glm::two_pi<float>() / 4.0f };

	glm::vec3 const venus_scale{ 0.05f };
	SpinConfiguration const venus_spin{ glm::radians(-2.6f), -glm::two_pi<float>() / 600.0f };
	OrbitConfiguration const venus_orbit{ 3.0f, glm::radians(-3.9f), glm::two_pi<float>() / 12.0f };

	glm::vec3 const earth_scale{ 0.05f };
	SpinConfiguration const earth_spin{ glm::radians(-23.0f), glm::two_pi<float>() / 3.0f };
	OrbitConfiguration const earth_orbit{ 4.0f, glm::radians(-7.2f), glm::two_pi<float>() / 20.0f };

	glm::vec3 const moon_scale{ 0.01f };
	SpinConfiguration const moon_spin{ glm::radians(-6.7f), glm::two_pi<float>() / 90.0f };
	OrbitConfiguration const moon_orbit{ 0.2f, glm::radians(29.0f), glm::two_pi<float>() / 1.3f };

	glm::vec3 const mars_scale{ 0.03f };
	SpinConfiguration const mars_spin{ glm::radians(-25.0f), glm::two_pi<float>() / 3.0f };
	OrbitConfiguration const mars_orbit{ 5.0f, glm::radians(-5.7f), glm::two_pi<float>() / 36.0f };

	glm::vec3 const jupiter_scale{ 0.5f };
	SpinConfiguration const jupiter_spin{ glm::radians(-3.1f), glm::two_pi<float>() / 1.0f };
	OrbitConfiguration const jupiter_orbit{ 13.0f, glm::radians(-6.1f), glm::two_pi<float>() / 220.0f };

	glm::vec3 const saturn_scale{ 0.4f };
	SpinConfiguration const saturn_spin{ glm::radians(-27.0f), glm::two_pi<float>() / 1.2f };
	OrbitConfiguration const saturn_orbit{ 16.0f, glm::radians(-5.5f), glm::two_pi<float>() / 400.0f };
	glm::vec2 const saturn_ring_scale{ 1.0f, 1.25f };

	glm::vec3 const uranus_scale{ 0.2f };
	SpinConfiguration const uranus_spin{ glm::radians(-82.0f), -glm::two_pi<float>() / 2.0f };
	OrbitConfiguration const uranus_orbit{ 18.0f, glm::radians(-6.5f), glm::two_pi<float>() / 1680.0f };

	glm::vec3 const neptune_scale{ 0.2f };
	SpinConfiguration const neptune_spin{ glm::radians(-28.0f), glm::two_pi<float>() / 2.0f };
	OrbitConfiguration const neptune_orbit{ 19.0f, glm::radians(-6.4f), glm::two_pi<float>() / 3200.0f };

	//
	// Load all textures.
	//
	GLuint const sun_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_sun.jpg"));
	GLuint const mercury_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_mercury.jpg"));
	GLuint const venus_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_venus_atmosphere.jpg"));
	GLuint const earth_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_earth_daymap.jpg"));
	GLuint const moon_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_moon.jpg"));
	GLuint const mars_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_mars.jpg"));
	GLuint const jupiter_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_jupiter.jpg"));
	GLuint const saturn_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_saturn.jpg"));
	GLuint const saturn_ring_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_saturn_ring_alpha.png"));
	GLuint const uranus_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_uranus.jpg"));
	GLuint const neptune_texture = bonobo::loadTexture2D(config::resources_path("planets/2k_neptune.jpg"));

	//
	// Set up the celestial bodies.
	//
	CelestialBody moon(sphere, &celestial_body_shader, moon_texture);
	moon.set_scale(glm::vec3(0.3f));
	moon.set_spin(moon_spin);
	moon.set_orbit({1.5f, glm::radians(-66.0f), glm::two_pi<float>() / 1.3f});

	CelestialBody earth(sphere, &celestial_body_shader, earth_texture);
	earth.set_spin(earth_spin);
	earth.set_orbit({-2.5f, glm::radians(45.0f), glm::two_pi<float>() / 10.0f});
	earth.add_child(&moon);

	//
	// Define the colour and depth used for clearing.
	//
	glClearDepthf(1.0f);
	glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
	glEnable(GL_DEPTH_TEST);

	auto last_time = std::chrono::high_resolution_clock::now();

	bool pause_animation = false;
	bool show_logs = true;
	bool show_gui = true;
	float time_scale = 1.0f;

	while (!glfwWindowShouldClose(window)) {
		//
		// Compute timings information
		//
		auto const now_time = std::chrono::high_resolution_clock::now();
		auto const delta_time_us = std::chrono::duration_cast<std::chrono::microseconds>(now_time - last_time);
		auto const animation_delta_time_us = !pause_animation ? std::chrono::duration_cast<std::chrono::microseconds>(delta_time_us * time_scale) : 0us;
		last_time = now_time;

		//
		// Process inputs
		//
		glfwPollEvents();

		ImGuiIO const& io = ImGui::GetIO();
		input_handler.SetUICapture(io.WantCaptureMouse, io.WantCaptureKeyboard);
		input_handler.Advance();
		camera.Update(delta_time_us, input_handler);

		if (input_handler.GetKeycodeState(GLFW_KEY_F3) & JUST_RELEASED)
			show_logs = !show_logs;
		if (input_handler.GetKeycodeState(GLFW_KEY_F2) & JUST_RELEASED)
			show_gui = !show_gui;
		if (input_handler.GetKeycodeState(GLFW_KEY_F11) & JUST_RELEASED)
			window_manager.ToggleFullscreenStatusForWindow(window);

		// Retrieve the actual framebuffer size: for HiDPI monitors,
		// you might end up with a framebuffer larger than what you
		// actually asked for. For example, if you ask for a 1920x1080
		// framebuffer, you might get a 3840x2160 one instead.
		// Also it might change as the user drags the window between
		// monitors with different DPIs, or if the fullscreen status is
		// being toggled.
		int framebuffer_width, framebuffer_height;
		glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
		glViewport(0, 0, framebuffer_width, framebuffer_height);

		//
		// Start a new frame for Dear ImGui
		//
		window_manager.NewImGuiFrame();

		//
		// Clear the screen
		//
		glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

		//
		// Traverse the scene graph and render all nodes
		//
		struct CelestialBodyRef
		{
			CelestialBody* body;
			glm::mat4 parent_transform;
		};
		// TODO: Replace this explicit rendering of the Earth and Moon
		// with a traversal of the scene graph and rendering of all its
		// nodes.
		earth.render(animation_delta_time_us, camera.GetWorldToClipMatrix(), glm::translate(glm::mat4(1.0f), glm::vec3(2.0f, 0.0f, 0.0f)));
		//moon.render(animation_delta_time_us, camera.GetWorldToClipMatrix());

		//
		// Add controls to the scene.
		//
		bool const opened = ImGui::Begin("Scene controls", nullptr, ImGuiWindowFlags_None);
		if (opened)
		{
			ImGui::Checkbox("Pause the animation", &pause_animation);
			ImGui::SliderFloat("Time scale", &time_scale, 1e-1f, 10.0f);
		}
		ImGui::End();

		//
		// Display Dear ImGui windows
		//
		if (show_logs)
			Log::View::Render();
		window_manager.RenderImGuiFrame(show_gui);

		//
		// Queue the computed frame for display on screen
		//
		glfwSwapBuffers(window);
	}

	glDeleteTextures(1, &neptune_texture);
	glDeleteTextures(1, &uranus_texture);
	glDeleteTextures(1, &saturn_ring_texture);
	glDeleteTextures(1, &saturn_texture);
	glDeleteTextures(1, &jupiter_texture);
	glDeleteTextures(1, &mars_texture);
	glDeleteTextures(1, &moon_texture);
	glDeleteTextures(1, &earth_texture);
	glDeleteTextures(1, &venus_texture);
	glDeleteTextures(1, &mars_texture);
	glDeleteTextures(1, &sun_texture);

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
Copyright 2016 Fixstars Corporation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http ://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>

#include <cuda_runtime.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <sl/Camera.hpp>

#include <libsgm.h>

template <class... Args>
static std::string format_string(const char* fmt, Args... args)
{
	const int BUF_SIZE = 1024;
	char buf[BUF_SIZE];
	std::snprintf(buf, BUF_SIZE, fmt, args...);
	return std::string(buf);
}

struct device_buffer {
	device_buffer() : data(nullptr) {}
	device_buffer(size_t count) { allocate(count); }
	void allocate(size_t count) { cudaMalloc(&data, count); }
	~device_buffer() { cudaFree(data); }
	void* data;
};

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

	const int disp_size = 128;

	sl::Camera zed;
	sl::InitParameters initParameters;
	initParameters.camera_resolution = sl::RESOLUTION_VGA;
	sl::ERROR_CODE err = zed.open(initParameters);
	if (err != sl::SUCCESS) {
		std::cout << toString(err) << std::endl;
		zed.close();
		return 1;
	}
	const int width = static_cast<int>(zed.getResolution().width);
	const int height = static_cast<int>(zed.getResolution().height);

	sl::Mat d_zed_image_l(zed.getResolution(), sl::MAT_TYPE_8U_C1, sl::MEM_GPU);
	sl::Mat d_zed_image_r(zed.getResolution(), sl::MAT_TYPE_8U_C1, sl::MEM_GPU);

	const int input_depth = 8;
	const int output_depth = 8;
	const int output_bytes = output_depth * width * height / 8;

	CV_Assert(d_zed_image_l.getStep(sl::MEM_GPU) == d_zed_image_r.getStep(sl::MEM_GPU));
	sgm::StereoSGM sgm(width, height, disp_size, input_depth, output_depth, static_cast<int>(d_zed_image_l.getStep(sl::MEM_GPU)), width, sgm::EXECUTE_INOUT_CUDA2CUDA);

	cv::Mat disparity(height, width, CV_8U);
	cv::Mat disparity_8u, disparity_color;

	device_buffer d_disparity(output_bytes);
	while (1) {
		if (zed.grab() == sl::SUCCESS) {
			zed.retrieveImage(d_zed_image_l, sl::VIEW_LEFT_GRAY, sl::MEM_GPU);
			zed.retrieveImage(d_zed_image_r, sl::VIEW_RIGHT_GRAY, sl::MEM_GPU);
		} else continue;

		const auto t1 = std::chrono::system_clock::now();

		sgm.execute(d_zed_image_l.getPtr<uchar>(sl::MEM_GPU), d_zed_image_r.getPtr<uchar>(sl::MEM_GPU), d_disparity.data);
		cudaDeviceSynchronize();

		const auto t2 = std::chrono::system_clock::now();
		const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
		const double fps = 1e6 / duration;

		cudaMemcpy(disparity.data, d_disparity.data, output_bytes, cudaMemcpyDeviceToHost);

		disparity.convertTo(disparity_8u, CV_8U, 255. / disp_size);
		cv::applyColorMap(disparity_8u, disparity_color, cv::COLORMAP_JET);
		cv::putText(disparity_color, format_string("sgm execution time: %4.1f[msec] %4.1f[FPS]", 1e-3 * duration, fps),
			cv::Point(50, 50), 2, 0.75, cv::Scalar(255, 255, 255));

		cv::imshow("disparity", disparity_color);
		const char c = cv::waitKey(1);
		if (c == 27) // ESC
			break;
	}
	zed.close();
	return 0;
}
<commit_msg>Set invalid disp to black at sample/zed<commit_after>/*
Copyright 2016 Fixstars Corporation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http ://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <stdlib.h>
#include <cstdint>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>

#include <cuda_runtime.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <sl/Camera.hpp>

#include <libsgm.h>

template <class... Args>
static std::string format_string(const char* fmt, Args... args)
{
	const int BUF_SIZE = 1024;
	char buf[BUF_SIZE];
	std::snprintf(buf, BUF_SIZE, fmt, args...);
	return std::string(buf);
}

struct device_buffer {
	device_buffer() : data(nullptr) {}
	device_buffer(size_t count) { allocate(count); }
	void allocate(size_t count) { cudaMalloc(&data, count); }
	~device_buffer() { cudaFree(data); }
	void* data;
};

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

	const int disp_size = 128;

	sl::Camera zed;
	sl::InitParameters initParameters;
	initParameters.camera_resolution = sl::RESOLUTION_VGA;
	sl::ERROR_CODE err = zed.open(initParameters);
	if (err != sl::SUCCESS) {
		std::cout << toString(err) << std::endl;
		zed.close();
		return 1;
	}
	const int width = static_cast<int>(zed.getResolution().width);
	const int height = static_cast<int>(zed.getResolution().height);

	sl::Mat d_zed_image_l(zed.getResolution(), sl::MAT_TYPE_8U_C1, sl::MEM_GPU);
	sl::Mat d_zed_image_r(zed.getResolution(), sl::MAT_TYPE_8U_C1, sl::MEM_GPU);

	const int input_depth = 8;
	const int output_depth = 8;
	const int output_bytes = output_depth * width * height / 8;

	CV_Assert(d_zed_image_l.getStep(sl::MEM_GPU) == d_zed_image_r.getStep(sl::MEM_GPU));
	sgm::StereoSGM sgm(width, height, disp_size, input_depth, output_depth, static_cast<int>(d_zed_image_l.getStep(sl::MEM_GPU)), width, sgm::EXECUTE_INOUT_CUDA2CUDA);

	cv::Mat disparity(height, width, CV_8U);
	cv::Mat disparity_8u, disparity_color;

	device_buffer d_disparity(output_bytes);
	while (1) {
		if (zed.grab() == sl::SUCCESS) {
			zed.retrieveImage(d_zed_image_l, sl::VIEW_LEFT_GRAY, sl::MEM_GPU);
			zed.retrieveImage(d_zed_image_r, sl::VIEW_RIGHT_GRAY, sl::MEM_GPU);
		} else continue;

		const auto t1 = std::chrono::system_clock::now();

		sgm.execute(d_zed_image_l.getPtr<uchar>(sl::MEM_GPU), d_zed_image_r.getPtr<uchar>(sl::MEM_GPU), d_disparity.data);
		cudaDeviceSynchronize();

		const auto t2 = std::chrono::system_clock::now();
		const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
		const double fps = 1e6 / duration;

		cudaMemcpy(disparity.data, d_disparity.data, output_bytes, cudaMemcpyDeviceToHost);

		disparity.convertTo(disparity_8u, CV_8U, 255. / disp_size);
		cv::applyColorMap(disparity_8u, disparity_color, cv::COLORMAP_JET);
		disparity_color.setTo(cv::Scalar(0, 0, 0), disparity == static_cast<std::uint8_t>(-1));
		cv::putText(disparity_color, format_string("sgm execution time: %4.1f[msec] %4.1f[FPS]", 1e-3 * duration, fps),
			cv::Point(50, 50), 2, 0.75, cv::Scalar(255, 255, 255));

		cv::imshow("disparity", disparity_color);
		const char c = cv::waitKey(1);
		if (c == 27) // ESC
			break;
	}
	zed.close();
	return 0;
}
<|endoftext|>


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

#define GLTFIO_SIMPLEVIEWER_IMPLEMENTATION

#include "app/Config.h"
#include "app/FilamentApp.h"
#include "app/IBL.h"

#include <filament/Engine.h>
#include <filament/Scene.h>
#include <filament/View.h>

#include <gltfio/AssetLoader.h>
#include <gltfio/FilamentAsset.h>
#include <gltfio/ResourceLoader.h>
#include <gltfio/SimpleViewer.h>

#include <getopt/getopt.h>

#include <utils/NameComponentManager.h>

#include <fstream>
#include <string>

#include "generated/resources/gltf.h"

using namespace filament;
using namespace gltfio;
using namespace utils;

struct App {
    Engine* engine;
    SimpleViewer* viewer;
    Config config;
    AssetLoader* loader;
    FilamentAsset* asset = nullptr;
    NameComponentManager* names;
    MaterialProvider* materials;
    MaterialSource materialSource = GENERATE_SHADERS;
    bool actualSize = false;
};

static const char* DEFAULT_IBL = "envs/venetian_crossroads";

static void printUsage(char* name) {
    std::string exec_name(Path(name).getName());
    std::string usage(
        "SHOWCASE renders the specified glTF file, or a built-in file if none is specified\n"
        "Usage:\n"
        "    SHOWCASE [options] <gltf path>\n"
        "Options:\n"
        "   --help, -h\n"
        "       Prints this message\n\n"
        "   --api, -a\n"
        "       Specify the backend API: opengl (default), vulkan, or metal\n\n"
        "   --ibl=<path to cmgen IBL>, -i <path>\n"
        "       Override the built-in IBL\n\n"
        "   --actual-size, -s\n"
        "       Do not scale the model to fit into a unit cube\n\n"
        "   --ubershader, -u\n"
        "       Enable ubershaders (improves load time, adds shader complexity)\n\n"
    );
    const std::string from("SHOWCASE");
    for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
        usage.replace(pos, from.length(), exec_name);
    }
    std::cout << usage;
}

static int handleCommandLineArguments(int argc, char* argv[], App* app) {
    static constexpr const char* OPTSTR = "ha:i:us";
    static const struct option OPTIONS[] = {
        { "help",       no_argument,       nullptr, 'h' },
        { "api",        required_argument, nullptr, 'a' },
        { "ibl",        required_argument, nullptr, 'i' },
        { "ubershader", no_argument,       nullptr, 'u' },
        { "actual-size", no_argument,      nullptr, 's' },
        { nullptr, 0, nullptr, 0 }
    };
    int opt;
    int option_index = 0;
    while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
        std::string arg(optarg ? optarg : "");
        switch (opt) {
            default:
            case 'h':
                printUsage(argv[0]);
                exit(0);
            case 'a':
                if (arg == "opengl") {
                    app->config.backend = Engine::Backend::OPENGL;
                } else if (arg == "vulkan") {
                    app->config.backend = Engine::Backend::VULKAN;
                } else if (arg == "metal") {
                    app->config.backend = Engine::Backend::METAL;
                } else {
                    std::cerr << "Unrecognized backend. Must be 'opengl'|'vulkan'|'metal'.\n";
                }
                break;
            case 'i':
                app->config.iblDirectory = arg;
                break;
            case 'u':
                app->materialSource = LOAD_UBERSHADERS;
                break;
            case 's':
                app->actualSize = true;
                break;
        }
    }
    return optind;
}

static std::ifstream::pos_type getFileSize(const char* filename) {
    std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
    return in.tellg();
}

int main(int argc, char** argv) {
    App app;

    app.config.title = "Filament";
    app.config.iblDirectory = FilamentApp::getRootPath() + DEFAULT_IBL;

    int option_index = handleCommandLineArguments(argc, argv, &app);
    utils::Path filename;
    int num_args = argc - option_index;
    if (num_args >= 1) {
        filename = argv[option_index];
        if (!filename.exists()) {
            std::cerr << "file " << filename << " not found!" << std::endl;
            return 1;
        }
        if (filename.isDirectory()) {
            auto files = filename.listContents();
            for (auto file : files) {
                if (file.getExtension() == "gltf" || file.getExtension() == "glb") {
                    filename = file;
                    break;
                }
            }
            if (filename.isDirectory()) {
                std::cerr << "no glTF file found in " << filename << std::endl;
                return 1;
            }
        }
    }

    auto loadAsset = [&app](utils::Path filename) {
        // Peek at the file size to allow pre-allocation.
        long contentSize = static_cast<long>(getFileSize(filename.c_str()));
        if (contentSize <= 0) {
            std::cerr << "Unable to open " << filename << std::endl;
            exit(1);
        }

        // Consume the glTF file.
        std::ifstream in(filename.c_str(), std::ifstream::in);
        std::vector<uint8_t> buffer(static_cast<unsigned long>(contentSize));
        if (!in.read((char*) buffer.data(), contentSize)) {
            std::cerr << "Unable to read " << filename << std::endl;
            exit(1);
        }

        // Parse the glTF file and create Filament entities.
        if (filename.getExtension() == "glb") {
            app.asset = app.loader->createAssetFromBinary(buffer.data(), buffer.size());
        } else {
            app.asset = app.loader->createAssetFromJson(buffer.data(), buffer.size());
        }
        buffer.clear();
        buffer.shrink_to_fit();

        if (!app.asset) {
            std::cerr << "Unable to parse " << filename << std::endl;
            exit(1);
        }
    };

    auto loadResources = [&app] (utils::Path filename) {
        // Load external textures and buffers.
        gltfio::ResourceLoader({
            .engine = app.engine,
            .gltfPath = filename.getAbsolutePath(),
            .normalizeSkinningWeights = true,
            .recomputeBoundingBoxes = false
        }).loadResources(app.asset);

        // Load animation data then free the source hierarchy.
        app.asset->getAnimator();
        app.asset->releaseSourceData();

        // Add the renderables to the scene.
        app.viewer->setAsset(app.asset, app.names, !app.actualSize);

        app.viewer->setIndirectLight(FilamentApp::get().getIBL()->getIndirectLight());
    };

    auto setup = [&](Engine* engine, View* view, Scene* scene) {
        app.engine = engine;
        app.names = new NameComponentManager(EntityManager::get());
        app.viewer = new SimpleViewer(engine, scene, view);
        app.materials = (app.materialSource == GENERATE_SHADERS) ?
                createMaterialGenerator(engine) : createUbershaderLoader(engine);
        app.loader = AssetLoader::create({engine, app.materials, app.names });
        if (filename.isEmpty()) {
            app.asset = app.loader->createAssetFromBinary(GLTF_DAMAGEDHELMET_DATA,
                    GLTF_DAMAGEDHELMET_SIZE);
        } else {
            loadAsset(filename);
        }

        loadResources(filename);

        app.viewer->setUiCallback([&app, scene] () {
            if (ImGui::CollapsingHeader("Stats")) {
                ImGui::Text("%zu entities in the asset", app.asset->getEntityCount());
                ImGui::Text("%zu renderables (excluding UI)", scene->getRenderableCount());
                ImGui::Text("%zu skipped frames", FilamentApp::get().getSkippedFrameCount());
            }
        });

        // Leave FXAA enabled but we also enable MSAA for a nice result. The wireframe looks
        // much better with MSAA enabled.
        view->setSampleCount(4);
    };

    auto cleanup = [&app](Engine* engine, View*, Scene*) {
        Fence::waitAndDestroy(engine->createFence());
        delete app.viewer;
        app.loader->destroyAsset(app.asset);
        app.materials->destroyMaterials();
        delete app.materials;
        AssetLoader::destroy(&app.loader);
        delete app.names;
    };

    auto animate = [&app](Engine* engine, View* view, double now) {
        app.viewer->applyAnimation(now);
    };

    auto gui = [&app](filament::Engine* engine, filament::View* view) {
        app.viewer->updateUserInterface();
        FilamentApp::get().setSidebarWidth(app.viewer->getSidebarWidth());
    };

    FilamentApp& filamentApp = FilamentApp::get();
    filamentApp.animate(animate);

    filamentApp.setDropHandler([&] (std::string path) {
        app.viewer->removeAsset();
        app.loader->destroyAsset(app.asset);
        loadAsset(path);
        loadResources(path);
    });

    filamentApp.run(app.config, setup, cleanup, gui);

    return 0;
}
<commit_msg>gltf_viewer should not crash when there is no IBL.<commit_after>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define GLTFIO_SIMPLEVIEWER_IMPLEMENTATION

#include "app/Config.h"
#include "app/FilamentApp.h"
#include "app/IBL.h"

#include <filament/Engine.h>
#include <filament/Scene.h>
#include <filament/View.h>

#include <gltfio/AssetLoader.h>
#include <gltfio/FilamentAsset.h>
#include <gltfio/ResourceLoader.h>
#include <gltfio/SimpleViewer.h>

#include <getopt/getopt.h>

#include <utils/NameComponentManager.h>

#include <fstream>
#include <string>

#include "generated/resources/gltf.h"

using namespace filament;
using namespace gltfio;
using namespace utils;

struct App {
    Engine* engine;
    SimpleViewer* viewer;
    Config config;
    AssetLoader* loader;
    FilamentAsset* asset = nullptr;
    NameComponentManager* names;
    MaterialProvider* materials;
    MaterialSource materialSource = GENERATE_SHADERS;
    bool actualSize = false;
};

static const char* DEFAULT_IBL = "envs/venetian_crossroads";

static void printUsage(char* name) {
    std::string exec_name(Path(name).getName());
    std::string usage(
        "SHOWCASE renders the specified glTF file, or a built-in file if none is specified\n"
        "Usage:\n"
        "    SHOWCASE [options] <gltf path>\n"
        "Options:\n"
        "   --help, -h\n"
        "       Prints this message\n\n"
        "   --api, -a\n"
        "       Specify the backend API: opengl (default), vulkan, or metal\n\n"
        "   --ibl=<path to cmgen IBL>, -i <path>\n"
        "       Override the built-in IBL\n\n"
        "   --actual-size, -s\n"
        "       Do not scale the model to fit into a unit cube\n\n"
        "   --ubershader, -u\n"
        "       Enable ubershaders (improves load time, adds shader complexity)\n\n"
    );
    const std::string from("SHOWCASE");
    for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
        usage.replace(pos, from.length(), exec_name);
    }
    std::cout << usage;
}

static int handleCommandLineArguments(int argc, char* argv[], App* app) {
    static constexpr const char* OPTSTR = "ha:i:us";
    static const struct option OPTIONS[] = {
        { "help",       no_argument,       nullptr, 'h' },
        { "api",        required_argument, nullptr, 'a' },
        { "ibl",        required_argument, nullptr, 'i' },
        { "ubershader", no_argument,       nullptr, 'u' },
        { "actual-size", no_argument,      nullptr, 's' },
        { nullptr, 0, nullptr, 0 }
    };
    int opt;
    int option_index = 0;
    while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
        std::string arg(optarg ? optarg : "");
        switch (opt) {
            default:
            case 'h':
                printUsage(argv[0]);
                exit(0);
            case 'a':
                if (arg == "opengl") {
                    app->config.backend = Engine::Backend::OPENGL;
                } else if (arg == "vulkan") {
                    app->config.backend = Engine::Backend::VULKAN;
                } else if (arg == "metal") {
                    app->config.backend = Engine::Backend::METAL;
                } else {
                    std::cerr << "Unrecognized backend. Must be 'opengl'|'vulkan'|'metal'.\n";
                }
                break;
            case 'i':
                app->config.iblDirectory = arg;
                break;
            case 'u':
                app->materialSource = LOAD_UBERSHADERS;
                break;
            case 's':
                app->actualSize = true;
                break;
        }
    }
    return optind;
}

static std::ifstream::pos_type getFileSize(const char* filename) {
    std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
    return in.tellg();
}

int main(int argc, char** argv) {
    App app;

    app.config.title = "Filament";
    app.config.iblDirectory = FilamentApp::getRootPath() + DEFAULT_IBL;

    int option_index = handleCommandLineArguments(argc, argv, &app);
    utils::Path filename;
    int num_args = argc - option_index;
    if (num_args >= 1) {
        filename = argv[option_index];
        if (!filename.exists()) {
            std::cerr << "file " << filename << " not found!" << std::endl;
            return 1;
        }
        if (filename.isDirectory()) {
            auto files = filename.listContents();
            for (auto file : files) {
                if (file.getExtension() == "gltf" || file.getExtension() == "glb") {
                    filename = file;
                    break;
                }
            }
            if (filename.isDirectory()) {
                std::cerr << "no glTF file found in " << filename << std::endl;
                return 1;
            }
        }
    }

    auto loadAsset = [&app](utils::Path filename) {
        // Peek at the file size to allow pre-allocation.
        long contentSize = static_cast<long>(getFileSize(filename.c_str()));
        if (contentSize <= 0) {
            std::cerr << "Unable to open " << filename << std::endl;
            exit(1);
        }

        // Consume the glTF file.
        std::ifstream in(filename.c_str(), std::ifstream::in);
        std::vector<uint8_t> buffer(static_cast<unsigned long>(contentSize));
        if (!in.read((char*) buffer.data(), contentSize)) {
            std::cerr << "Unable to read " << filename << std::endl;
            exit(1);
        }

        // Parse the glTF file and create Filament entities.
        if (filename.getExtension() == "glb") {
            app.asset = app.loader->createAssetFromBinary(buffer.data(), buffer.size());
        } else {
            app.asset = app.loader->createAssetFromJson(buffer.data(), buffer.size());
        }
        buffer.clear();
        buffer.shrink_to_fit();

        if (!app.asset) {
            std::cerr << "Unable to parse " << filename << std::endl;
            exit(1);
        }
    };

    auto loadResources = [&app] (utils::Path filename) {
        // Load external textures and buffers.
        gltfio::ResourceLoader({
            .engine = app.engine,
            .gltfPath = filename.getAbsolutePath(),
            .normalizeSkinningWeights = true,
            .recomputeBoundingBoxes = false
        }).loadResources(app.asset);

        // Load animation data then free the source hierarchy.
        app.asset->getAnimator();
        app.asset->releaseSourceData();

        // Add the renderables to the scene.
        app.viewer->setAsset(app.asset, app.names, !app.actualSize);

        auto ibl = FilamentApp::get().getIBL();
        if (ibl) {
            app.viewer->setIndirectLight(ibl->getIndirectLight());
        }
    };

    auto setup = [&](Engine* engine, View* view, Scene* scene) {
        app.engine = engine;
        app.names = new NameComponentManager(EntityManager::get());
        app.viewer = new SimpleViewer(engine, scene, view);
        app.materials = (app.materialSource == GENERATE_SHADERS) ?
                createMaterialGenerator(engine) : createUbershaderLoader(engine);
        app.loader = AssetLoader::create({engine, app.materials, app.names });
        if (filename.isEmpty()) {
            app.asset = app.loader->createAssetFromBinary(GLTF_DAMAGEDHELMET_DATA,
                    GLTF_DAMAGEDHELMET_SIZE);
        } else {
            loadAsset(filename);
        }

        loadResources(filename);

        app.viewer->setUiCallback([&app, scene] () {
            if (ImGui::CollapsingHeader("Stats")) {
                ImGui::Text("%zu entities in the asset", app.asset->getEntityCount());
                ImGui::Text("%zu renderables (excluding UI)", scene->getRenderableCount());
                ImGui::Text("%zu skipped frames", FilamentApp::get().getSkippedFrameCount());
            }
        });

        // Leave FXAA enabled but we also enable MSAA for a nice result. The wireframe looks
        // much better with MSAA enabled.
        view->setSampleCount(4);
    };

    auto cleanup = [&app](Engine* engine, View*, Scene*) {
        Fence::waitAndDestroy(engine->createFence());
        delete app.viewer;
        app.loader->destroyAsset(app.asset);
        app.materials->destroyMaterials();
        delete app.materials;
        AssetLoader::destroy(&app.loader);
        delete app.names;
    };

    auto animate = [&app](Engine* engine, View* view, double now) {
        app.viewer->applyAnimation(now);
    };

    auto gui = [&app](filament::Engine* engine, filament::View* view) {
        app.viewer->updateUserInterface();
        FilamentApp::get().setSidebarWidth(app.viewer->getSidebarWidth());
    };

    FilamentApp& filamentApp = FilamentApp::get();
    filamentApp.animate(animate);

    filamentApp.setDropHandler([&] (std::string path) {
        app.viewer->removeAsset();
        app.loader->destroyAsset(app.asset);
        loadAsset(path);
        loadResources(path);
    });

    filamentApp.run(app.config, setup, cleanup, gui);

    return 0;
}
<|endoftext|>


<commit_before>/************************************************
 *  tok.hpp
 *  ESA++
 *
 *  Copyright (c) 2014, Chi-En Wu
 *  Distributed under The BSD 3-Clause License
 ************************************************/

#ifndef ESAPP_TOK_HPP_
#define ESAPP_TOK_HPP_

#include <cctype>
#include <array>
#include <string>

namespace esapp
{

/************************************************
 * Inline Helper Function(s)
 ************************************************/

inline bool ischs(int c)
{
    return c >= u'\u4E00' && c <= u'\u9FFF';
}

/************************************************
 * Declaration: class TokenIterator
 ************************************************/

class TokenIterator
{
public: // Public Type(s)
    typedef std::wstring Sequence;
    typedef Sequence::const_iterator Iterator;

    typedef std::input_iterator_tag iterator_category;
    typedef Sequence value_type;
    typedef ptrdiff_t difference_type;
    typedef value_type const *pointer;
    typedef value_type const &reference;

public: // Public Method(s)
    TokenIterator(Sequence const &sequence);
    TokenIterator(Iterator const &begin, Iterator const &end);

    TokenIterator end(void) const;
    bool at_end(void) const;

    TokenIterator &operator++(void);
    TokenIterator operator++(int);

    reference operator*(void) const;
    pointer operator->(void) const;

    bool operator==(TokenIterator const &it) const;
    bool operator!=(TokenIterator const &it) const;

private: // Private Method(s)
    template <typename Predicate>
    void skip(Predicate pred);

    template <typename Predicate>
    bool scan(Predicate pred);

private: // Private Property(ies)
    Iterator begin_;
    Iterator end_;
    Sequence token_;
    bool at_end_;
}; // class TokenIterator

/************************************************
 * Implementation: class TokenIterator
 ************************************************/

inline TokenIterator::TokenIterator(Sequence const &sequence)
    : TokenIterator(sequence.begin(), sequence.end())
{
    // do nothing
}

inline TokenIterator::TokenIterator(Iterator const &begin, Iterator const &end)
    : begin_(begin), end_(end), at_end_(begin_ == end_)
{
    if (!at_end_) { ++(*this); }
}

inline TokenIterator TokenIterator::end(void) const
{
    return TokenIterator(end_, end_);
}

inline bool TokenIterator::at_end(void) const
{
    return at_end_;
}

inline TokenIterator &TokenIterator::operator++(void)
{
    skip(&isspace);
    if (begin_ == end_)
    {
        at_end_ = true;
        token_.clear();
    }
    else if (!scan(&ischs) && !scan(&isalnum))
    {
        token_.assign(1, *begin_);
        ++begin_;
    }

    return *this;
}

inline TokenIterator TokenIterator::operator++(int)
{
    decltype((*this)++) it(*this);
    ++(*this);
    return it;
}

inline TokenIterator::reference TokenIterator::operator*(void) const
{
    return token_;
}

inline TokenIterator::pointer TokenIterator::operator->(void) const
{
    return &token_;
}

inline bool TokenIterator::operator==(TokenIterator const &it) const
{
    return begin_ == it.begin_ && at_end_ == it.at_end_;
}

inline bool TokenIterator::operator!=(TokenIterator const &it) const
{
    return !(*this == it);
}

template <typename Predicate>
inline void TokenIterator::skip(Predicate pred)
{
    for ( ; begin_ != end_ && pred(*begin_); ++begin_) { /* do nothing */ }
}

template <typename Predicate>
inline bool TokenIterator::scan(Predicate pred)
{
    auto begin = begin_;
    skip(pred);

    bool scanned = begin != begin_;
    if (scanned) { token_.assign(begin, begin_); }

    return scanned;
}

} // namespace esa

#endif // ESAPP_TOK_HPP_
<commit_msg>Remove unnecessary include statement<commit_after>/************************************************
 *  tok.hpp
 *  ESA++
 *
 *  Copyright (c) 2014, Chi-En Wu
 *  Distributed under The BSD 3-Clause License
 ************************************************/

#ifndef ESAPP_TOK_HPP_
#define ESAPP_TOK_HPP_

#include <cctype>
#include <string>

namespace esapp
{

/************************************************
 * Inline Helper Function(s)
 ************************************************/

inline bool ischs(int c)
{
    return c >= u'\u4E00' && c <= u'\u9FFF';
}

/************************************************
 * Declaration: class TokenIterator
 ************************************************/

class TokenIterator
{
public: // Public Type(s)
    typedef std::wstring Sequence;
    typedef Sequence::const_iterator Iterator;

    typedef std::input_iterator_tag iterator_category;
    typedef Sequence value_type;
    typedef ptrdiff_t difference_type;
    typedef value_type const *pointer;
    typedef value_type const &reference;

public: // Public Method(s)
    TokenIterator(Sequence const &sequence);
    TokenIterator(Iterator const &begin, Iterator const &end);

    TokenIterator end(void) const;
    bool at_end(void) const;

    TokenIterator &operator++(void);
    TokenIterator operator++(int);

    reference operator*(void) const;
    pointer operator->(void) const;

    bool operator==(TokenIterator const &it) const;
    bool operator!=(TokenIterator const &it) const;

private: // Private Method(s)
    template <typename Predicate>
    void skip(Predicate pred);

    template <typename Predicate>
    bool scan(Predicate pred);

private: // Private Property(ies)
    Iterator begin_;
    Iterator end_;
    Sequence token_;
    bool at_end_;
}; // class TokenIterator

/************************************************
 * Implementation: class TokenIterator
 ************************************************/

inline TokenIterator::TokenIterator(Sequence const &sequence)
    : TokenIterator(sequence.begin(), sequence.end())
{
    // do nothing
}

inline TokenIterator::TokenIterator(Iterator const &begin, Iterator const &end)
    : begin_(begin), end_(end), at_end_(begin_ == end_)
{
    if (!at_end_) { ++(*this); }
}

inline TokenIterator TokenIterator::end(void) const
{
    return TokenIterator(end_, end_);
}

inline bool TokenIterator::at_end(void) const
{
    return at_end_;
}

inline TokenIterator &TokenIterator::operator++(void)
{
    skip(&isspace);
    if (begin_ == end_)
    {
        at_end_ = true;
        token_.clear();
    }
    else if (!scan(&ischs) && !scan(&isalnum))
    {
        token_.assign(1, *begin_);
        ++begin_;
    }

    return *this;
}

inline TokenIterator TokenIterator::operator++(int)
{
    decltype((*this)++) it(*this);
    ++(*this);
    return it;
}

inline TokenIterator::reference TokenIterator::operator*(void) const
{
    return token_;
}

inline TokenIterator::pointer TokenIterator::operator->(void) const
{
    return &token_;
}

inline bool TokenIterator::operator==(TokenIterator const &it) const
{
    return begin_ == it.begin_ && at_end_ == it.at_end_;
}

inline bool TokenIterator::operator!=(TokenIterator const &it) const
{
    return !(*this == it);
}

template <typename Predicate>
inline void TokenIterator::skip(Predicate pred)
{
    for ( ; begin_ != end_ && pred(*begin_); ++begin_) { /* do nothing */ }
}

template <typename Predicate>
inline bool TokenIterator::scan(Predicate pred)
{
    auto begin = begin_;
    skip(pred);

    bool scanned = begin != begin_;
    if (scanned) { token_.assign(begin, begin_); }

    return scanned;
}

} // namespace esa

#endif // ESAPP_TOK_HPP_
<|endoftext|>


<commit_before>#include <babylon/materials/pbr/pbr_material_defines.h>

namespace BABYLON {

PBRMaterialDefines::PBRMaterialDefines() : MaterialDefines{}
{
  _keys = {
    "PBR",
    "MAINUV1",
    "MAINUV2",
    "UV1",
    "UV2",
    "ALBEDO",
    "VERTEXCOLOR",
    "AMBIENT",
    "AMBIENTINGRAYSCALE",
    "OPACITY",
    "VERTEXALPHA",
    "OPACITYRGB",
    "ALPHATEST",
    "ALPHABLEND",
    "ALPHAFROMALBEDO",
    "SPECULAROVERALPHA",
    "RADIANCEOVERALPHA",
    "ALPHAFRESNEL",
    "PREMULTIPLYALPHA",
    "EMISSIVE",
    "REFLECTIVITY",
    "SPECULARTERM",
    "MICROSURFACEFROMREFLECTIVITYMAP",
    "MICROSURFACEAUTOMATIC",
    "LODBASEDMICROSFURACE",
    "MICROSURFACEMAP",
    "METALLICWORKFLOW",
    "ROUGHNESSSTOREINMETALMAPALPHA",
    "ROUGHNESSSTOREINMETALMAPGREEN",
    "METALLNESSSTOREINMETALMAPBLUE",
    "AOSTOREINMETALMAPRED",
    "ENVIRONMENTBRDF",
    "NORMAL",
    "TANGENT",
    "BUMP",
    "PARALLAX",
    "PARALLAXOCCLUSION",
    "INVERTNORMALMAPX",
    "INVERTNORMALMAPY",
    "NORMALXYSCALE",
    "LIGHTMAP",
    "USELIGHTMAPASSHADOWMAP",
    "REFLECTION",
    "REFLECTIONMAP_3D",
    "REFLECTIONMAP_SPHERICAL",
    "REFLECTIONMAP_PLANAR",
    "REFLECTIONMAP_CUBIC",
    "REFLECTIONMAP_PROJECTION",
    "REFLECTIONMAP_SKYBOX",
    "REFLECTIONMAP_EXPLICIT",
    "REFLECTIONMAP_EQUIRECTANGULAR",
    "REFLECTIONMAP_EQUIRECTANGULAR_FIXED",
    "REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED",
    "INVERTCUBICMAP",
    "USESPHERICALFROMREFLECTIONMAP",
    "USESPHERICALINFRAGMENT",
    "REFLECTIONMAP_OPPOSITEZ",
    "LODINREFLECTIONALPHA",
    "GAMMAREFLECTION",
    "REFRACTION",
    "REFRACTIONMAP_3D",
    "REFRACTIONMAP_OPPOSITEZ",
    "LODINREFRACTIONALPHA",
    "GAMMAREFRACTION",
    "LINKREFRACTIONTOTRANSPARENCY",
    "INSTANCES",
    "MORPHTARGETS",
    "MORPHTARGETS_NORMAL",
    "MORPHTARGETS_TANGENT",
    "IMAGEPROCESSING",
    "VIGNETTE",
    "VIGNETTEBLENDMODEMULTIPLY",
    "VIGNETTEBLENDMODEOPAQUE",
    "TONEMAPPING",
    "CONTRAST",
    "COLORCURVES",
    "COLORGRADING",
    "SAMPLER3DGREENDEPTH",
    "SAMPLER3DBGRMAP",
    "IMAGEPROCESSINGPOSTPROCESS",
    "EXPOSURE",
    "USEPHYSICALLIGHTFALLOFF",
    "TWOSIDEDLIGHTING",
    "SHADOWFLOAT",
    "USERIGHTHANDEDSYSTEM",
    "CLIPPLANE",
    "POINTSIZE",
    "FOG",
    "LOGARITHMICDEPTH",
  };
  rebuild();
}

PBRMaterialDefines::~PBRMaterialDefines()
{
}

void PBRMaterialDefines::reset()
{
  MaterialDefines::reset();
  ALPHATESTVALUE = 0.5f;
  PBR            = true;
}

} // end of namespace BABYLON<commit_msg>Fixed PBR setting<commit_after>#include <babylon/materials/pbr/pbr_material_defines.h>

namespace BABYLON {

PBRMaterialDefines::PBRMaterialDefines() : MaterialDefines{}
{
  _keys = {
    "PBR",
    "MAINUV1",
    "MAINUV2",
    "UV1",
    "UV2",
    "ALBEDO",
    "VERTEXCOLOR",
    "AMBIENT",
    "AMBIENTINGRAYSCALE",
    "OPACITY",
    "VERTEXALPHA",
    "OPACITYRGB",
    "ALPHATEST",
    "ALPHABLEND",
    "ALPHAFROMALBEDO",
    "SPECULAROVERALPHA",
    "RADIANCEOVERALPHA",
    "ALPHAFRESNEL",
    "PREMULTIPLYALPHA",
    "EMISSIVE",
    "REFLECTIVITY",
    "SPECULARTERM",
    "MICROSURFACEFROMREFLECTIVITYMAP",
    "MICROSURFACEAUTOMATIC",
    "LODBASEDMICROSFURACE",
    "MICROSURFACEMAP",
    "METALLICWORKFLOW",
    "ROUGHNESSSTOREINMETALMAPALPHA",
    "ROUGHNESSSTOREINMETALMAPGREEN",
    "METALLNESSSTOREINMETALMAPBLUE",
    "AOSTOREINMETALMAPRED",
    "ENVIRONMENTBRDF",
    "NORMAL",
    "TANGENT",
    "BUMP",
    "PARALLAX",
    "PARALLAXOCCLUSION",
    "INVERTNORMALMAPX",
    "INVERTNORMALMAPY",
    "NORMALXYSCALE",
    "LIGHTMAP",
    "USELIGHTMAPASSHADOWMAP",
    "REFLECTION",
    "REFLECTIONMAP_3D",
    "REFLECTIONMAP_SPHERICAL",
    "REFLECTIONMAP_PLANAR",
    "REFLECTIONMAP_CUBIC",
    "REFLECTIONMAP_PROJECTION",
    "REFLECTIONMAP_SKYBOX",
    "REFLECTIONMAP_EXPLICIT",
    "REFLECTIONMAP_EQUIRECTANGULAR",
    "REFLECTIONMAP_EQUIRECTANGULAR_FIXED",
    "REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED",
    "INVERTCUBICMAP",
    "USESPHERICALFROMREFLECTIONMAP",
    "USESPHERICALINFRAGMENT",
    "REFLECTIONMAP_OPPOSITEZ",
    "LODINREFLECTIONALPHA",
    "GAMMAREFLECTION",
    "REFRACTION",
    "REFRACTIONMAP_3D",
    "REFRACTIONMAP_OPPOSITEZ",
    "LODINREFRACTIONALPHA",
    "GAMMAREFRACTION",
    "LINKREFRACTIONTOTRANSPARENCY",
    "INSTANCES",
    "MORPHTARGETS",
    "MORPHTARGETS_NORMAL",
    "MORPHTARGETS_TANGENT",
    "IMAGEPROCESSING",
    "VIGNETTE",
    "VIGNETTEBLENDMODEMULTIPLY",
    "VIGNETTEBLENDMODEOPAQUE",
    "TONEMAPPING",
    "CONTRAST",
    "COLORCURVES",
    "COLORGRADING",
    "SAMPLER3DGREENDEPTH",
    "SAMPLER3DBGRMAP",
    "IMAGEPROCESSINGPOSTPROCESS",
    "EXPOSURE",
    "USEPHYSICALLIGHTFALLOFF",
    "TWOSIDEDLIGHTING",
    "SHADOWFLOAT",
    "USERIGHTHANDEDSYSTEM",
    "CLIPPLANE",
    "POINTSIZE",
    "FOG",
    "LOGARITHMICDEPTH",
  };
  rebuild();
}

PBRMaterialDefines::~PBRMaterialDefines()
{
}

void PBRMaterialDefines::reset()
{
  MaterialDefines::reset();
  ALPHATESTVALUE = 0.5f;
  defines[PBR]   = true;
}

} // end of namespace BABYLON
<|endoftext|>