<commit_before>////////////////////////////////////////////////////////////////////////
//
// Implementation of oscillations of neutrinos in matter in a
// three-neutrino framework with NSI.
//
// This  class inherits from the PMNS_Fast class
//
// coelho@lal.in2p3.fr
////////////////////////////////////////////////////////////////////////

#include "PMNS_NSI.h"
#include "MatrixDecomp/zheevh3.h"

#include <iostream>
#include <cassert>
#include <stdlib.h>

using namespace OscProb;

using namespace std;

//......................................................................
///
/// Constructor. \sa PMNS_Base::PMNS_Base
///
/// This class is restricted to 3 neutrino flavours.
///
PMNS_NSI::PMNS_NSI() : PMNS_Fast(), fEps()
{
  SetStdPath();
  SetNSI(0.,0.,0.,0.,0.,0.,0.,0.,0.);
  SetFermCoup(1,0,0);
}

//......................................................................
///
/// Nothing to clean.
///
PMNS_NSI::~PMNS_NSI(){}

//......................................................................
///
/// Set all NSI parameters at once.
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param eps_ee      - The real parameter eps_ee
/// @param eps_emu     - The absolute value of the complex parameter eps_emu
/// @param eps_etau    - The absolute value of the complex parameter eps_etau
/// @param eps_mumu    - The real parameter eps_mumu
/// @param eps_mutau   - The absolute value of the complex parameter eps_mutau
/// @param eps_tautau  - The real parameter eps_tautau
/// @param delta_emu   - The phase of the complex parameter eps_emu in radians
/// @param delta_etau  - The phase of the complex parameter eps_etau in radians
/// @param delta_mutau - The phase of the complex parameter eps_mutau in radians
///
void PMNS_NSI::SetNSI(double eps_ee,    double eps_emu,    double eps_etau,
                       double eps_mumu,  double eps_mutau,  double eps_tautau,
                       double delta_emu, double delta_etau, double delta_mutau)
{

  SetEps(0,0, eps_ee,     0);
  SetEps(1,1, eps_mumu,   0);
  SetEps(2,2, eps_tautau, 0);

  SetEps(0,1, eps_emu,   delta_emu);
  SetEps(0,2, eps_etau,  delta_etau);
  SetEps(1,2, eps_mutau, delta_mutau);

}

//......................................................................
///
/// Set any given NSI parameter.
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// Flavours are:\n
/// - 0 = nue, 1 = numu, 2 = nutau
///
/// Requires that flvi < flvj. Will notify you if input is wrong.
/// If flvi > flvj, will assume reverse order and swap flvi and flvj.
///
/// @param flvi  - The first flavour index
/// @param flvj  - The second flavour index
/// @param val   - The absolute value of the parameter
/// @param phase - The complex phase of the parameter in radians
///
void PMNS_NSI::SetEps(int flvi, int flvj, double val, double phase){

  if(flvi > flvj){
    cout << "First argument should be smaller or equal to second argument" << endl;
    cout << "Setting reverse order (Eps_" << flvj << flvi << "). " << endl;
    int temp = flvi;
    flvi = flvj;
    flvj = temp;
  }
  if(flvi<0 || flvi>2 || flvj < flvi || flvj > 2){
    cout << "Eps_" << flvi << flvj << " not valid for " << fNumNus;
    cout << " neutrinos. Doing nothing." << endl;
    return;
  }

  complex h = val;

  if(flvi != flvj) h *= complex(cos(phase), sin(phase));

  fGotES *= (fEps[flvi][flvj] == h);

  fEps[flvi][flvj] = h;

}

//......................................................................
///
/// Get any given NSI parameter.
///
/// Flavours are:\n
/// - 0 = nue, 1 = numu, 2 = nutau
///
/// Requires that flvi < flvj. Will notify you if input is wrong.
/// If flvi > flvj, will assume reverse order and swap flvi and flvj.
///
/// @param flvi  - The first flavour index
/// @param flvj  - The second flavour index
///
complex<double> PMNS_NSI::GetEps(int flvi, int flvj){

  if(flvi > flvj){
    cout << "First argument should be smaller or equal to second argument" << endl;
    cout << "Setting reverse order (Eps_" << flvj << flvi << "). " << endl;
    int temp = flvi;
    flvi = flvj;
    flvj = temp;
  }
  if(flvi<0 || flvi>2 || flvj < flvi || flvj > 2){
    cout << "Eps_" << flvi << flvj << " not valid for " << fNumNus;
    cout << " neutrinos. Returning 0." << endl;
    return zero;
  }

  return fEps[flvi][flvj];

}

//......................................................................
///
/// Set eps_ee parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a - The value of the real parameter eps_ee
///
void PMNS_NSI::SetEps_ee(double a){ SetEps(0,0, a, 0); }

//......................................................................
///
/// Set eps_mumu parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a - The value of the real parameter eps_mumu
///
void PMNS_NSI::SetEps_mumu(double a){ SetEps(1,1, a, 0); }

//......................................................................
///
/// Set eps_tautau parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a - The value of the real parameter eps_tautau
///
void PMNS_NSI::SetEps_tautau(double a){ SetEps(2,2, a, 0); }

//......................................................................
///
/// Set eps_emu parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a   - The absolute value of the parameter eps_emu
/// @param phi - The phase of the complex parameter eps_emu in radians
///
void PMNS_NSI::SetEps_emu  (double a, double phi){ SetEps(0,1, a, phi); }

//......................................................................
///
/// Set eps_etau parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a   - The absolute value of the parameter eps_etau
/// @param phi - The phase of the complex parameter eps_etau in radians
///
void PMNS_NSI::SetEps_etau  (double a, double phi){ SetEps(0,2, a, phi); }

//......................................................................
///
/// Set eps_mutau parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a   - The absolute value of the parameter eps_mutau
/// @param phi - The phase of the complex parameter eps_mutau in radians
///
void PMNS_NSI::SetEps_mutau  (double a, double phi){ SetEps(1,2, a, phi); }

//......................................................................
///
/// Build the full Hamiltonian in matter
///
/// Here we divide the mass squared matrix Hms by the 2E
/// to obtain the vacuum Hamiltonian in eV. Then, the matter
/// potential is added to each flavour pair.
///
void PMNS_NSI::UpdateHam()
{

  double lv = 2 * kGeV2eV*fEnergy;           // 2*E in eV

  double kr2GNe   = kK2*M_SQRT2*kGf * fPath.density;
  double kr2GNnsi = kr2GNe;

  kr2GNe   *= fPath.zoa;    // Std matter potential in eV
  kr2GNnsi *= GetZoACoup(); // NSI matter potential in eV

  // Finish build Hamiltonian in matter with dimension of eV
  for(int i=0;i<fNumNus;i++){
    for(int j=i;j<fNumNus;j++){
      if(!fIsNuBar) fHam[i][j] = fHms[i][j]/lv + kr2GNnsi*fEps[i][j];
      else          fHam[i][j] = conj(fHms[i][j]/lv - kr2GNnsi*fEps[i][j]);
    }
  }

  if(!fIsNuBar) fHam[0][0] += kr2GNe;
  else          fHam[0][0] -= kr2GNe;

}

//......................................................................
///
/// Set the NSI relative coupling to electrons.
/// This factor represents what fraction of the electrons are seen
/// by the interaction.
///
void PMNS_NSI::SetElecCoup(double e){

  fGotES *= (fNSIcoup[0] == e);

  fNSIcoup[0] = e;

}

//......................................................................
///
/// Set the NSI relative coupling to u-quarks.
/// This factor represents what fraction of the u-quarks are seen
/// by the interaction.
///
void PMNS_NSI::SetUpCoup(double u){

  fGotES *= (fNSIcoup[1] == u);

  fNSIcoup[1] = u;

}

//......................................................................
///
/// Set the NSI relative coupling to d-quarks.
/// This factor represents what fraction of the d-quarks are seen
/// by the interaction.
///
void PMNS_NSI::SetDownCoup(double d){

  fGotES *= (fNSIcoup[2] == d);

  fNSIcoup[2] = d;

}

//......................................................................
///
/// Set the NSI relative couplings to each fermion.
/// These factors represent what fraction of each fermion are seen
/// by the interaction.
///
void PMNS_NSI::SetFermCoup(double e, double u, double d)
{

  SetElecCoup(e); // electron coupling
  SetUpCoup(u);   // u-quark coupling
  SetDownCoup(d); // d-quark coupling

}

//......................................................................
///
/// Get the NSI relative coupling to electrons.
///
double PMNS_NSI::GetElecCoup(){ return fNSIcoup[0]; }

//......................................................................
///
/// Get the NSI relative coupling to u-quarks.
///
double PMNS_NSI::GetUpCoup(){ return fNSIcoup[1]; }

//......................................................................
///
/// Get the NSI relative coupling to d-quarks.
///
double PMNS_NSI::GetDownCoup(){ return fNSIcoup[2]; }

//......................................................................
///
/// Get the effective NSI Z/A dependence.
///
double PMNS_NSI::GetZoACoup()
{

  return fNSIcoup[0] * fPath.zoa        // electrons: Z
       + fNSIcoup[1] * (1 + fPath.zoa)  // u-quarks:  A + Z
       + fNSIcoup[2] * (2 - fPath.zoa); // d-quarks: 2A - Z

}

////////////////////////////////////////////////////////////////////////
<commit_msg>Add documentation for coupling parameters<commit_after>////////////////////////////////////////////////////////////////////////
//
// Implementation of oscillations of neutrinos in matter in a
// three-neutrino framework with NSI.
//
// This  class inherits from the PMNS_Fast class
//
// coelho@lal.in2p3.fr
////////////////////////////////////////////////////////////////////////

#include "PMNS_NSI.h"
#include "MatrixDecomp/zheevh3.h"

#include <iostream>
#include <cassert>
#include <stdlib.h>

using namespace OscProb;

using namespace std;

//......................................................................
///
/// Constructor. \sa PMNS_Base::PMNS_Base
///
/// This class is restricted to 3 neutrino flavours.
///
PMNS_NSI::PMNS_NSI() : PMNS_Fast(), fEps()
{
  SetStdPath();
  SetNSI(0.,0.,0.,0.,0.,0.,0.,0.,0.);
  SetFermCoup(1,0,0);
}

//......................................................................
///
/// Nothing to clean.
///
PMNS_NSI::~PMNS_NSI(){}

//......................................................................
///
/// Set all NSI parameters at once.
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param eps_ee      - The real parameter eps_ee
/// @param eps_emu     - The absolute value of the complex parameter eps_emu
/// @param eps_etau    - The absolute value of the complex parameter eps_etau
/// @param eps_mumu    - The real parameter eps_mumu
/// @param eps_mutau   - The absolute value of the complex parameter eps_mutau
/// @param eps_tautau  - The real parameter eps_tautau
/// @param delta_emu   - The phase of the complex parameter eps_emu in radians
/// @param delta_etau  - The phase of the complex parameter eps_etau in radians
/// @param delta_mutau - The phase of the complex parameter eps_mutau in radians
///
void PMNS_NSI::SetNSI(double eps_ee,    double eps_emu,    double eps_etau,
                       double eps_mumu,  double eps_mutau,  double eps_tautau,
                       double delta_emu, double delta_etau, double delta_mutau)
{

  SetEps(0,0, eps_ee,     0);
  SetEps(1,1, eps_mumu,   0);
  SetEps(2,2, eps_tautau, 0);

  SetEps(0,1, eps_emu,   delta_emu);
  SetEps(0,2, eps_etau,  delta_etau);
  SetEps(1,2, eps_mutau, delta_mutau);

}

//......................................................................
///
/// Set any given NSI parameter.
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// Flavours are:\n
/// - 0 = nue, 1 = numu, 2 = nutau
///
/// Requires that flvi < flvj. Will notify you if input is wrong.
/// If flvi > flvj, will assume reverse order and swap flvi and flvj.
///
/// @param flvi  - The first flavour index
/// @param flvj  - The second flavour index
/// @param val   - The absolute value of the parameter
/// @param phase - The complex phase of the parameter in radians
///
void PMNS_NSI::SetEps(int flvi, int flvj, double val, double phase){

  if(flvi > flvj){
    cout << "First argument should be smaller or equal to second argument" << endl;
    cout << "Setting reverse order (Eps_" << flvj << flvi << "). " << endl;
    int temp = flvi;
    flvi = flvj;
    flvj = temp;
  }
  if(flvi<0 || flvi>2 || flvj < flvi || flvj > 2){
    cout << "Eps_" << flvi << flvj << " not valid for " << fNumNus;
    cout << " neutrinos. Doing nothing." << endl;
    return;
  }

  complex h = val;

  if(flvi != flvj) h *= complex(cos(phase), sin(phase));

  fGotES *= (fEps[flvi][flvj] == h);

  fEps[flvi][flvj] = h;

}

//......................................................................
///
/// Get any given NSI parameter.
///
/// Flavours are:\n
/// - 0 = nue, 1 = numu, 2 = nutau
///
/// Requires that flvi < flvj. Will notify you if input is wrong.
/// If flvi > flvj, will assume reverse order and swap flvi and flvj.
///
/// @param flvi  - The first flavour index
/// @param flvj  - The second flavour index
///
complex<double> PMNS_NSI::GetEps(int flvi, int flvj){

  if(flvi > flvj){
    cout << "First argument should be smaller or equal to second argument" << endl;
    cout << "Setting reverse order (Eps_" << flvj << flvi << "). " << endl;
    int temp = flvi;
    flvi = flvj;
    flvj = temp;
  }
  if(flvi<0 || flvi>2 || flvj < flvi || flvj > 2){
    cout << "Eps_" << flvi << flvj << " not valid for " << fNumNus;
    cout << " neutrinos. Returning 0." << endl;
    return zero;
  }

  return fEps[flvi][flvj];

}

//......................................................................
///
/// Set eps_ee parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a - The value of the real parameter eps_ee
///
void PMNS_NSI::SetEps_ee(double a){ SetEps(0,0, a, 0); }

//......................................................................
///
/// Set eps_mumu parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a - The value of the real parameter eps_mumu
///
void PMNS_NSI::SetEps_mumu(double a){ SetEps(1,1, a, 0); }

//......................................................................
///
/// Set eps_tautau parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a - The value of the real parameter eps_tautau
///
void PMNS_NSI::SetEps_tautau(double a){ SetEps(2,2, a, 0); }

//......................................................................
///
/// Set eps_emu parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a   - The absolute value of the parameter eps_emu
/// @param phi - The phase of the complex parameter eps_emu in radians
///
void PMNS_NSI::SetEps_emu  (double a, double phi){ SetEps(0,1, a, phi); }

//......................................................................
///
/// Set eps_etau parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a   - The absolute value of the parameter eps_etau
/// @param phi - The phase of the complex parameter eps_etau in radians
///
void PMNS_NSI::SetEps_etau  (double a, double phi){ SetEps(0,2, a, phi); }

//......................................................................
///
/// Set eps_mutau parameter
///
/// This will check if value is changing to keep track of whether
/// the eigensystem needs to be recomputed.
///
/// @param a   - The absolute value of the parameter eps_mutau
/// @param phi - The phase of the complex parameter eps_mutau in radians
///
void PMNS_NSI::SetEps_mutau  (double a, double phi){ SetEps(1,2, a, phi); }

//......................................................................
///
/// Build the full Hamiltonian in matter
///
/// Here we divide the mass squared matrix Hms by the 2E
/// to obtain the vacuum Hamiltonian in eV. Then, the matter
/// potential is added to each flavour pair.
///
void PMNS_NSI::UpdateHam()
{

  double lv = 2 * kGeV2eV*fEnergy;           // 2*E in eV

  double kr2GNe   = kK2*M_SQRT2*kGf * fPath.density;
  double kr2GNnsi = kr2GNe;

  kr2GNe   *= fPath.zoa;    // Std matter potential in eV
  kr2GNnsi *= GetZoACoup(); // NSI matter potential in eV

  // Finish build Hamiltonian in matter with dimension of eV
  for(int i=0;i<fNumNus;i++){
    for(int j=i;j<fNumNus;j++){
      if(!fIsNuBar) fHam[i][j] = fHms[i][j]/lv + kr2GNnsi*fEps[i][j];
      else          fHam[i][j] = conj(fHms[i][j]/lv - kr2GNnsi*fEps[i][j]);
    }
  }

  if(!fIsNuBar) fHam[0][0] += kr2GNe;
  else          fHam[0][0] -= kr2GNe;

}

//......................................................................
///
/// Set the NSI relative coupling to electrons.
/// This factor represents what fraction of the electrons are seen
/// by the interaction.
///
/// @param e - electron coupling strength
///
void PMNS_NSI::SetElecCoup(double e){

  fGotES *= (fNSIcoup[0] == e);

  fNSIcoup[0] = e;

}

//......................................................................
///
/// Set the NSI relative coupling to u-quarks.
/// This factor represents what fraction of the u-quarks are seen
/// by the interaction.
///
/// @param u - u-quark coupling strength
///
void PMNS_NSI::SetUpCoup(double u){

  fGotES *= (fNSIcoup[1] == u);

  fNSIcoup[1] = u;

}

//......................................................................
///
/// Set the NSI relative coupling to d-quarks.
/// This factor represents what fraction of the d-quarks are seen
/// by the interaction.
///
/// @param d - d-quark coupling strength
///
void PMNS_NSI::SetDownCoup(double d){

  fGotES *= (fNSIcoup[2] == d);

  fNSIcoup[2] = d;

}

//......................................................................
///
/// Set the NSI relative couplings to each fermion.
/// These factors represent what fraction of each fermion are seen
/// by the interaction.
///
/// @param e - electron coupling strength
/// @param u - u-quark coupling strength
/// @param d - d-quark coupling strength
///
void PMNS_NSI::SetFermCoup(double e, double u, double d)
{

  SetElecCoup(e); // electron coupling
  SetUpCoup(u);   // u-quark coupling
  SetDownCoup(d); // d-quark coupling

}

//......................................................................
///
/// Get the NSI relative coupling to electrons.
///
double PMNS_NSI::GetElecCoup(){ return fNSIcoup[0]; }

//......................................................................
///
/// Get the NSI relative coupling to u-quarks.
///
double PMNS_NSI::GetUpCoup(){ return fNSIcoup[1]; }

//......................................................................
///
/// Get the NSI relative coupling to d-quarks.
///
double PMNS_NSI::GetDownCoup(){ return fNSIcoup[2]; }

//......................................................................
///
/// Get the effective NSI Z/A dependence.
///
double PMNS_NSI::GetZoACoup()
{

  return fNSIcoup[0] * fPath.zoa        // electrons: Z
       + fNSIcoup[1] * (1 + fPath.zoa)  // u-quarks:  A + Z
       + fNSIcoup[2] * (2 - fPath.zoa); // d-quarks: 2A - Z

}

////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>
#include "CommandParser.cpp"
#include "Configurations.h"
#include "Utils.cpp"

namespace L10ns {

void printDefaultHelp() {
    auto w = new TextWriter();
    w->writeLine("usage: l10ns <command> [<options>]");
    w->newline();
    w->writeLine("Commands:");
    for (const auto& action : actions) {
        w->writeLine(*action.name + " " + *action.description);
    }
    w->print();
}

void printActionHelp(ActionKind action) {

}

void printCommandHelp(Command * command) {
    if (command->action == ActionKind::None) {
        printDefaultHelp();
    }
    else {
        printActionHelp(command->action);
    }
}

int init(int argc, char * argv[]) {
    auto command = parseCommandArguments(argc, argv);
    if (command->isRequestingVersion) {
        println("L10ns version ", VERSION, ".");
    }
    else if (command->isRequestingHelp) {
        printCommandHelp(command);
    }
    return 0;
}

} // L10ns
<commit_msg>Adds inlining<commit_after>
#include "CommandParser.cpp"
#include "Configurations.h"
#include "Utils.cpp"

namespace L10ns {

inline void printDefaultHelp() {
    auto w = new TextWriter();
    w->addTab(2);
    w->addTab(10);
    w->writeLine("Usage: l10ns <command> [<options>]");
    w->newline();
    w->writeLine("Commands:");
    for (const auto& action : actions) {
        w->writeLine(*action.name + " " + *action.description);
    }
    w->print();
}

inline void printActionHelp(ActionKind action) {

}

inline void printCommandHelp(Command * command) {
    if (command->action == ActionKind::None) {
        printDefaultHelp();
    }
    else {
        printActionHelp(command->action);
    }
}

int init(int argc, char * argv[]) {
    auto command = parseCommandArguments(argc, argv);
    if (command->isRequestingVersion) {
        println("L10ns version ", VERSION, ".");
    }
    else if (command->isRequestingHelp) {
        printCommandHelp(command);
    }
    return 0;
}

} // L10ns
<|endoftext|>


<commit_before>#include "Particle.h"
#include "Globals.h"
#include <iostream>

Particle::Particle(glm::vec3 basePosVector, glm::vec3 aDirectionVector, glm::vec3 normVector, float aLen)
{
	this->init(basePosVector, aDirectionVector, normVector, aLen);
	this->normVector = normVector;

}

Particle::Particle(glm::vec3 basePosVector, glm::vec3 aDirectionVector, float aLen)
{
	this->init(basePosVector, aDirectionVector, getUprightNormVector(aDirectionVector),
		aLen);

}

void Particle::init(glm::vec3 basePosVector, glm::vec3 aDirectionVector, glm::vec3 normVector, float aLen)
{
	this->basePositionVector = basePosVector;
	this->vertexArrayIDParticle = 0;
	this->positionVector.resize(3);
	this->directionVector = normalizeVector(aDirectionVector);
	this->len = aLen;
	setPeak(basePosVector);
	setBasePositions(basePosVector, normVector);
	this->velocity = VELOCITY;
}

void Particle::draw()
{
	//if (!vertexArrayIDParticle)
		generateParticle();
	glBindVertexArray(vertexArrayIDParticle);//-> Daten zum Wrfel, VertexArrayObjekt wird an Shader weitergegeben
	glDrawArrays(GL_TRIANGLES, 0, 3*3); // 12*3 indices starting at 0 -> 12 triangles
}

void Particle::move()
{
	/*std::vector<glm::vec3> tmp = Particle::getNextPosition();
	for (int i = 0; i < 3; i++)
		this->positionVector.at(i) = tmp.at(i);*/
	/*for (int i = 0; i < 3; i++)
	{
		this->positionVector[i] = this->positionVector[i] + this->directionVector *
																	velocity;
	}*/

	this->basePositionVector += this->directionVector * velocity;
	glm::vec3 norm = getUprightNormVector(this->directionVector);
	setBasePositions(this->basePositionVector, norm);
	setPeak(this->basePositionVector);

}

std::vector<glm::vec3> Particle::getNextPosition() //NR
{
	std::vector<glm::vec3> ret;
	ret.resize(3);
	for (int i = 0; i < 3; i++)
		ret.at(i) = this->positionVector.at(i) + this->directionVector * velocity;
	return ret;
}

void Particle::generateParticle()
{
	glGenVertexArrays(1, &vertexArrayIDParticle); //Erzeuge VertexArrayObjekt
	glBindVertexArray(vertexArrayIDParticle); //Binde das erzeugte Objekt

	static GLfloat g_vertex_buffer_data[9];
	/*static GLfloat g_vertex_buffer_data[] = //war mal const
	{
		this->positionVector.at(0).x, this->positionVector.at(0).y, this->positionVector.at(0).z,
		this->positionVector.at(1).x, this->positionVector.at(1).y, this->positionVector.at(1).z,
		this->positionVector.at(2).x, this->positionVector.at(2).y, this->positionVector.at(2).z,
	};*/
	for (int i = 0, j = 0; i < 3; i++)
	{
		g_vertex_buffer_data[j++] = this->positionVector[i].x;
		g_vertex_buffer_data[j++] = this->positionVector[i].y;
		g_vertex_buffer_data[j++] = this->positionVector[i].z;
	}

	glGenBuffers(1, &vertexbuffer);

	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

	//Farbwerte des Partikels, mal sehen wies wird
	static const GLfloat g_color_buffer_data[] =
	{
		0.111f,  0.777f,  0.666f,
		0.333f,  0.444f,  0.555f,
		0.222f,  0.333f,  0.777f
	};

	glGenBuffers(1, &colorbuffer); //Adresse des Buffers anfordern
	glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); //Aufruf: angeforderten Buffer benutzen
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW); //Daten fr den Buffer definieren, Gre, Flag: Daten werden sich wohl nicht ndern

	glEnableVertexAttribArray(0); // Kein Disable ausfhren ! In Sepeicherbereich 0 des Shaders schreiben
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glVertexAttribPointer(
			0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
			3,                  // size
			GL_FLOAT,           // type
			GL_FALSE,           // normalized?
			0,                  // stride
			(void*)0            // array buffer offset
	);

	// 2nd attribute buffer : colors
	glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
	glEnableVertexAttribArray(1); // Kein Disable ausfhren ! In Speicherbereich 2 des Shaders schreiben
	glVertexAttribPointer(
			1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
			3,                                // size
			GL_FLOAT,                         // type
			GL_FALSE,                         // normalized?
			0,                                // stride
			(void*)0                          // array buffer offset
	);

	//glBindVertexArray(0);
}

void Particle::clearBuffers()
{
	glDeleteBuffers(1, &vertexbuffer);
	glDeleteBuffers(1, &colorbuffer);
}

void Particle::addToDirectionVector(glm::vec3 vector)
{
	//this->directionVector += normalizeVector(vector);
	this->directionVector = normalizeVector(vector);
}

glm::vec3 Particle::getDirectionVector()
{
	return this->directionVector;
}

void Particle::setPositionVector(std::vector<glm::vec3> vector)
{
	this->positionVector = vector;
}

void Particle::setVelocity(float velocity)
{
	this->velocity = velocity;
}

void Particle::toggleReadyForDraw()
{
	(this->readyForDraw) ? this->readyForDraw = false : this->readyForDraw = true;
}

void Particle::setPeak(glm::vec3 basePosVector)
{
	this->positionVector[2] = basePosVector + this->directionVector * len;
}

glm::vec3 Particle::getBasePosition()
{
	return basePositionVector;
}

void Particle::setBasePositions(glm::vec3 basePosVector, glm::vec3 normVector)
{
	normVector = this->normalizeVector(normVector);
	this->positionVector[0] = basePosVector + normVector * (len / 2);
	this->positionVector[1] = basePosVector + normVector * (-len / 2);
}

glm::vec3 Particle::normalizeVector(glm::vec3 toNormalize)
{
	if (toNormalize.x == 0 && toNormalize.y == 0 && toNormalize.z == 0)
		return toNormalize;
	return glm::normalize(toNormalize);

}

glm::vec3 Particle::getUprightNormVector(glm::vec3 toNorm)
{
	glm::vec3 ret = glm::vec3(0.0f, -(toNorm.z), toNorm.y);
	return ret;
}

Particle::~Particle(void)
{
}

<commit_msg>fixed memory leak<commit_after>#include "Particle.h"
#include "Globals.h"
#include <iostream>

Particle::Particle(glm::vec3 basePosVector, glm::vec3 aDirectionVector, glm::vec3 normVector, float aLen)
{
	this->init(basePosVector, aDirectionVector, normVector, aLen);
	this->normVector = normVector;

}

Particle::Particle(glm::vec3 basePosVector, glm::vec3 aDirectionVector, float aLen)
{
	this->init(basePosVector, aDirectionVector, getUprightNormVector(aDirectionVector),
		aLen);

}

void Particle::init(glm::vec3 basePosVector, glm::vec3 aDirectionVector, glm::vec3 normVector, float aLen)
{
	this->basePositionVector = basePosVector;
	this->vertexArrayIDParticle = 0;
	this->positionVector.resize(3);
	this->directionVector = normalizeVector(aDirectionVector);
	this->len = aLen;
	setPeak(basePosVector);
	setBasePositions(basePosVector, normVector);
	this->velocity = VELOCITY;
}

void Particle::draw()
{
	//if (!vertexArrayIDParticle)
		generateParticle();
	glBindVertexArray(vertexArrayIDParticle);//-> Daten zum Wrfel, VertexArrayObjekt wird an Shader weitergegeben
	glDrawArrays(GL_TRIANGLES, 0, 3*3); // 12*3 indices starting at 0 -> 12 triangles
}

void Particle::move()
{
	/*std::vector<glm::vec3> tmp = Particle::getNextPosition();
	for (int i = 0; i < 3; i++)
		this->positionVector.at(i) = tmp.at(i);*/
	/*for (int i = 0; i < 3; i++)
	{
		this->positionVector[i] = this->positionVector[i] + this->directionVector *
																	velocity;
	}*/

	this->basePositionVector += this->directionVector * velocity;
	glm::vec3 norm = getUprightNormVector(this->directionVector);
	setBasePositions(this->basePositionVector, norm);
	setPeak(this->basePositionVector);

}

std::vector<glm::vec3> Particle::getNextPosition() //NR
{
	std::vector<glm::vec3> ret;
	ret.resize(3);
	for (int i = 0; i < 3; i++)
		ret.at(i) = this->positionVector.at(i) + this->directionVector * velocity;
	return ret;
}

void Particle::generateParticle()
{
	glGenVertexArrays(1, &vertexArrayIDParticle); //Erzeuge VertexArrayObjekt
	glBindVertexArray(vertexArrayIDParticle); //Binde das erzeugte Objekt

	static GLfloat g_vertex_buffer_data[9];
	/*static GLfloat g_vertex_buffer_data[] = //war mal const
	{
		this->positionVector.at(0).x, this->positionVector.at(0).y, this->positionVector.at(0).z,
		this->positionVector.at(1).x, this->positionVector.at(1).y, this->positionVector.at(1).z,
		this->positionVector.at(2).x, this->positionVector.at(2).y, this->positionVector.at(2).z,
	};*/
	for (int i = 0, j = 0; i < 3; i++)
	{
		g_vertex_buffer_data[j++] = this->positionVector[i].x;
		g_vertex_buffer_data[j++] = this->positionVector[i].y;
		g_vertex_buffer_data[j++] = this->positionVector[i].z;
	}

	glGenBuffers(1, &vertexbuffer);

	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

	//Farbwerte des Partikels, mal sehen wies wird
	static const GLfloat g_color_buffer_data[] =
	{
		0.111f,  0.777f,  0.666f,
		0.333f,  0.444f,  0.555f,
		0.222f,  0.333f,  0.777f
	};

	glGenBuffers(1, &colorbuffer); //Adresse des Buffers anfordern
	glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); //Aufruf: angeforderten Buffer benutzen
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW); //Daten fr den Buffer definieren, Gre, Flag: Daten werden sich wohl nicht ndern

	glEnableVertexAttribArray(0); // Kein Disable ausfhren ! In Sepeicherbereich 0 des Shaders schreiben
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glVertexAttribPointer(
			0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
			3,                  // size
			GL_FLOAT,           // type
			GL_FALSE,           // normalized?
			0,                  // stride
			(void*)0            // array buffer offset
	);

	// 2nd attribute buffer : colors
	glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
	glEnableVertexAttribArray(1); // Kein Disable ausfhren ! In Speicherbereich 2 des Shaders schreiben
	glVertexAttribPointer(
			1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
			3,                                // size
			GL_FLOAT,                         // type
			GL_FALSE,                         // normalized?
			0,                                // stride
			(void*)0                          // array buffer offset
	);

	//glBindVertexArray(0);
}

void Particle::clearBuffers()
{
    glDeleteVertexArrays(1, &vertexArrayIDParticle);
	glDeleteBuffers(1, &vertexbuffer);
	glDeleteBuffers(1, &colorbuffer);
}

void Particle::addToDirectionVector(glm::vec3 vector)
{
	//this->directionVector += normalizeVector(vector);
	this->directionVector = normalizeVector(vector);
}

glm::vec3 Particle::getDirectionVector()
{
	return this->directionVector;
}

void Particle::setPositionVector(std::vector<glm::vec3> vector)
{
	this->positionVector = vector;
}

void Particle::setVelocity(float velocity)
{
	this->velocity = velocity;
}

void Particle::toggleReadyForDraw()
{
	(this->readyForDraw) ? this->readyForDraw = false : this->readyForDraw = true;
}

void Particle::setPeak(glm::vec3 basePosVector)
{
	this->positionVector[2] = basePosVector + this->directionVector * len;
}

glm::vec3 Particle::getBasePosition()
{
	return basePositionVector;
}

void Particle::setBasePositions(glm::vec3 basePosVector, glm::vec3 normVector)
{
	normVector = this->normalizeVector(normVector);
	this->positionVector[0] = basePosVector + normVector * (len / 2);
	this->positionVector[1] = basePosVector + normVector * (-len / 2);
}

glm::vec3 Particle::normalizeVector(glm::vec3 toNormalize)
{
	if (toNormalize.x == 0 && toNormalize.y == 0 && toNormalize.z == 0)
		return toNormalize;
	return glm::normalize(toNormalize);

}

glm::vec3 Particle::getUprightNormVector(glm::vec3 toNorm)
{
	glm::vec3 ret = glm::vec3(0.0f, -(toNorm.z), toNorm.y);
	return ret;
}

Particle::~Particle(void)
{
}

<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Crytek
 *
 * 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 "os/os_specific.h"

#include "serialise/string_utils.h"
#include "common/threading.h"

#include <windows.h>
#include <tlhelp32.h>

#include <algorithm>
#include <vector>
#include <map>
using std::vector;
using std::map;

struct FunctionHook
{
	FunctionHook(const char *f, void **o, void *d)
		: function(f), origptr(o), hookptr(d), excludeModule(NULL)
	{}

	bool operator <(const FunctionHook &h)
	{
		return function < h.function;
	}

	bool ApplyHook(void **IATentry)
	{
		DWORD oldProtection = PAGE_EXECUTE;

		if(*IATentry == hookptr)
			return false;

		BOOL success = TRUE;

		success = VirtualProtect(IATentry, sizeof(void*), PAGE_READWRITE, &oldProtection);
		if(!success)
		{
			RDCERR("Failed to make IAT entry writeable 0x%p", IATentry);
			return false;
		}

		if(origptr && *origptr == NULL) *origptr = *IATentry;

		*IATentry = hookptr;

		success = VirtualProtect(IATentry, sizeof(void*), oldProtection, &oldProtection);
		if(!success)
		{
			RDCERR("Failed to restore IAT entry protection 0x%p", IATentry);
			return false;
		}

		return true;
	}

	string function;
	void **origptr;
	void *hookptr;
	HMODULE excludeModule;
};

struct DllHookset
{
	DllHookset() : module(NULL) {}

	HMODULE module;
	vector<FunctionHook> FunctionHooks;
};

struct CachedHookData
{
	map<string, DllHookset> DllHooks;
	HMODULE module;
	Threading::CriticalSection lock;
	char lowername[512];

	void ApplyHooks(const char *modName, HMODULE module)
	{
		{
			size_t i=0;
			while(modName[i])
			{
				lowername[i] = (char)tolower(modName[i]);
				i++;
			}
			lowername[i] = 0;
		}

		// fraps seems to non-safely modify the assembly around the hook function, if
		// we modify its import descriptors it leads to a crash as it hooks OUR functions.
		// instead, skip modifying the import descriptors, it will hook the 'real' d3d functions
		// and we can call them and have fraps + renderdoc playing nicely together.
		// we also exclude some other overlay renderers here, such as steam's
		if(strstr(lowername, "fraps") ||
		   strstr(lowername, "gameoverlayrenderer"))
				return;

		// for safety (and because we don't need to), ignore these modules
		if(!_stricmp(modName, "kernel32.dll") ||
			!_stricmp(modName, "powrprof.dll") ||
			 strstr(lowername, "msvcr") == lowername ||
			 strstr(lowername, "msvcp") == lowername)
				return;

		// set module pointer if we are hooking exports from this module
		for(auto it=DllHooks.begin(); it != DllHooks.end(); ++it)
			if(!_stricmp(it->first.c_str(), modName))
				it->second.module = module;

		byte *baseAddress = (byte *)module;

		PIMAGE_DOS_HEADER dosheader = (PIMAGE_DOS_HEADER)baseAddress;

		if(dosheader->e_magic != 0x5a4d)
		{
			RDCDEBUG("Ignoring module %s, since magic is 0x%04x not 0x%04x", modName, (uint32_t)dosheader->e_magic, 0x5a4dU);
			return;
		}

		char *PE00 = (char *)(baseAddress + dosheader->e_lfanew);
		PIMAGE_FILE_HEADER fileHeader = (PIMAGE_FILE_HEADER)(PE00+4);
		PIMAGE_OPTIONAL_HEADER optHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)fileHeader+sizeof(IMAGE_FILE_HEADER));

		DWORD iatSize = optHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
		DWORD iatOffset = optHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

		IMAGE_IMPORT_DESCRIPTOR *importDesc = (IMAGE_IMPORT_DESCRIPTOR *)(baseAddress + iatOffset);

		while(iatOffset && importDesc->FirstThunk)
		{
			const char *dllName = (const char *)(baseAddress + importDesc->Name);

			DllHookset *hookset = NULL;

			for(auto it=DllHooks.begin(); it != DllHooks.end(); ++it)
				if(!_stricmp(it->first.c_str(), dllName))
					hookset = &it->second;

			if(hookset && importDesc->OriginalFirstThunk > 0 && importDesc->FirstThunk > 0)
			{
				IMAGE_THUNK_DATA *origFirst = (IMAGE_THUNK_DATA *)(baseAddress + importDesc->OriginalFirstThunk);
				IMAGE_THUNK_DATA *first = (IMAGE_THUNK_DATA *)(baseAddress + importDesc->FirstThunk);

				while(origFirst->u1.AddressOfData)
				{
#ifdef WIN64
					if(origFirst->u1.AddressOfData & 0x8000000000000000)
#else
					if(origFirst->u1.AddressOfData & 0x80000000)
#endif
					{
						// low bits of origFirst->u1.AddressOfData contain an ordinal
						origFirst++;
						first++;
						continue;
					}

					IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(baseAddress + origFirst->u1.AddressOfData);
					void **IATentry = (void **)&first->u1.AddressOfData;

					struct hook_find
					{
						bool operator() (const FunctionHook &a, const char *b)
						{ return strcmp(a.function.c_str(), b) < 0; }
					};

					const char *importName = (const char *)import->Name;
					auto found = std::lower_bound(hookset->FunctionHooks.begin(), hookset->FunctionHooks.end(), importName, hook_find());

					if(found != hookset->FunctionHooks.end() && !strcmp(found->function.c_str(), importName) && found->excludeModule != module)
					{
						SCOPED_LOCK(lock);
						bool applied = found->ApplyHook(IATentry);

						if(!applied)
							return;
					}

					origFirst++;
					first++;
				}
			}

			importDesc++;
		}
	}
};

static CachedHookData *s_HookData = NULL;

static void HookAllModules()
{
	HANDLE hModuleSnap = INVALID_HANDLE_VALUE;

	// up to 10 retries
	for(int i=0; i < 10; i++)
	{
		hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());

		if(hModuleSnap == INVALID_HANDLE_VALUE)
		{
			DWORD err = GetLastError();

			RDCWARN("CreateToolhelp32Snapshot() -> 0x%08x", err);

			// retry if error is ERROR_BAD_LENGTH
			if(err == ERROR_BAD_LENGTH)
				continue;
		}

		// didn't retry, or succeeded
		break;
	}

	if(hModuleSnap == INVALID_HANDLE_VALUE)
	{
		RDCERR("Couldn't create toolhelp dump of modules in process");
		return;
	}

#ifdef UNICODE
#undef MODULEENTRY32
#undef Module32First
#undef Module32Next
#endif

  MODULEENTRY32 me32;
	RDCEraseEl(me32);
  me32.dwSize = sizeof(MODULEENTRY32);

	BOOL success = Module32First(hModuleSnap, &me32);

  if(success == FALSE)
  {
		DWORD err = GetLastError();

		RDCERR("Couldn't get first module in process: 0x%08x", err);
    CloseHandle(hModuleSnap);
		return;
  }

	uintptr_t ret = 0;

	int numModules = 0;

  do
  {
		s_HookData->ApplyHooks(me32.szModule, me32.hModule);
  } while(ret == 0 && Module32Next(hModuleSnap, &me32));

  CloseHandle(hModuleSnap);
}

HMODULE WINAPI Hooked_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE fileHandle, DWORD flags)
{
	// we can use the function naked, as when setting up the hook for LoadLibraryExA, our own module
	// was excluded from IAT patching
	HMODULE mod = LoadLibraryExA(lpLibFileName, fileHandle, flags);

	HookAllModules();

	return mod;
}

HMODULE WINAPI Hooked_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE fileHandle, DWORD flags)
{
	// we can use the function naked, as when setting up the hook for LoadLibraryExA, our own module
	// was excluded from IAT patching
	HMODULE mod = LoadLibraryExW(lpLibFileName, fileHandle, flags);

	HookAllModules();

	return mod;
}

HMODULE WINAPI Hooked_LoadLibraryA(LPCSTR lpLibFileName)
{
	return Hooked_LoadLibraryExA(lpLibFileName, NULL, 0);
}

HMODULE WINAPI Hooked_LoadLibraryW(LPCWSTR lpLibFileName)
{
	return Hooked_LoadLibraryExW(lpLibFileName, NULL, 0);
}

static bool OrdinalAsString(void *func)
{
	return uint64_t(func) <= 0xffff;
}

FARPROC WINAPI Hooked_GetProcAddress(HMODULE mod, LPCSTR func)
{
	if(mod == NULL || func == NULL)
		return (FARPROC)NULL;

	if(mod == s_HookData->module || OrdinalAsString((void *)func))
		return GetProcAddress(mod, func);

	for(auto it=s_HookData->DllHooks.begin(); it != s_HookData->DllHooks.end(); ++it)
	{
		if(it->second.module == NULL)
			it->second.module = GetModuleHandleA(it->first.c_str());

		if(mod == it->second.module)
		{
			FunctionHook search(func, NULL, NULL);

			auto found = std::lower_bound(it->second.FunctionHooks.begin(), it->second.FunctionHooks.end(), search);
			if(found != it->second.FunctionHooks.end() && !(search < *found))
			{
				if(found->origptr && *found->origptr == NULL)
					*found->origptr = (void *)GetProcAddress(mod, func);

				return (FARPROC)found->hookptr;
			}
		}
	}

	return GetProcAddress(mod, func);
}

void Win32_IAT_BeginHooks()
{
	s_HookData = new CachedHookData;
	RDCASSERT(s_HookData->DllHooks.empty());
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryA", NULL, &Hooked_LoadLibraryA));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryW", NULL, &Hooked_LoadLibraryW));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryExA", NULL, &Hooked_LoadLibraryExA));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryExW", NULL, &Hooked_LoadLibraryExW));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("GetProcAddress", NULL, &Hooked_GetProcAddress));

	GetModuleHandleEx(
		GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
		(LPCTSTR)&s_HookData,
		&s_HookData->module);

	for(auto it=s_HookData->DllHooks.begin(); it != s_HookData->DllHooks.end(); ++it)
		for(size_t i=0; i < it->second.FunctionHooks.size(); i++)
			it->second.FunctionHooks[i].excludeModule = s_HookData->module;
}

// hook all functions for currently loaded modules.
// some of these hooks (as above) will hook LoadLibrary/GetProcAddress, to protect
void Win32_IAT_EndHooks()
{
	for(auto it=s_HookData->DllHooks.begin(); it != s_HookData->DllHooks.end(); ++it)
		std::sort(it->second.FunctionHooks.begin(), it->second.FunctionHooks.end());

	HookAllModules();
}

bool Win32_IAT_Hook(void **orig_function_ptr, const char *module_name, const char *function, void *destination_function_ptr)
{
	if(!_stricmp(module_name, "kernel32.dll"))
	{
		if(!strcmp(function, "LoadLibraryA") ||
			!strcmp(function, "LoadLibraryW") ||
			!strcmp(function, "LoadLibraryExA") ||
			!strcmp(function, "LoadLibraryExW") ||
			!strcmp(function, "GetProcAddress"))
		{
			RDCERR("Cannot hook LoadLibrary* or GetProcAddress, as these are hooked internally");
			return false;
		}
	}
	s_HookData->DllHooks[strlower(string(module_name))].FunctionHooks.push_back(FunctionHook(function, orig_function_ptr, destination_function_ptr));
	return true;
}
<commit_msg>Try to avoid hooking into module that was unloaded elsewhere.<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Crytek
 *
 * 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 "os/os_specific.h"

#include "serialise/string_utils.h"
#include "common/threading.h"

#include <windows.h>
#include <tlhelp32.h>

#include <algorithm>
#include <vector>
#include <map>
using std::vector;
using std::map;

struct FunctionHook
{
	FunctionHook(const char *f, void **o, void *d)
		: function(f), origptr(o), hookptr(d), excludeModule(NULL)
	{}

	bool operator <(const FunctionHook &h)
	{
		return function < h.function;
	}

	bool ApplyHook(void **IATentry)
	{
		DWORD oldProtection = PAGE_EXECUTE;

		if(*IATentry == hookptr)
			return false;

		BOOL success = TRUE;

		success = VirtualProtect(IATentry, sizeof(void*), PAGE_READWRITE, &oldProtection);
		if(!success)
		{
			RDCERR("Failed to make IAT entry writeable 0x%p", IATentry);
			return false;
		}

		if(origptr && *origptr == NULL) *origptr = *IATentry;

		*IATentry = hookptr;

		success = VirtualProtect(IATentry, sizeof(void*), oldProtection, &oldProtection);
		if(!success)
		{
			RDCERR("Failed to restore IAT entry protection 0x%p", IATentry);
			return false;
		}

		return true;
	}

	string function;
	void **origptr;
	void *hookptr;
	HMODULE excludeModule;
};

struct DllHookset
{
	DllHookset() : module(NULL) {}

	HMODULE module;
	vector<FunctionHook> FunctionHooks;
};

struct CachedHookData
{
	map<string, DllHookset> DllHooks;
	HMODULE module;
	Threading::CriticalSection lock;
	char lowername[512];

	void ApplyHooks(const char *modName, HMODULE module)
	{
		{
			size_t i=0;
			while(modName[i])
			{
				lowername[i] = (char)tolower(modName[i]);
				i++;
			}
			lowername[i] = 0;
		}

		// fraps seems to non-safely modify the assembly around the hook function, if
		// we modify its import descriptors it leads to a crash as it hooks OUR functions.
		// instead, skip modifying the import descriptors, it will hook the 'real' d3d functions
		// and we can call them and have fraps + renderdoc playing nicely together.
		// we also exclude some other overlay renderers here, such as steam's
		if(strstr(lowername, "fraps") ||
		   strstr(lowername, "gameoverlayrenderer"))
				return;

		// for safety (and because we don't need to), ignore these modules
		if(!_stricmp(modName, "kernel32.dll") ||
			!_stricmp(modName, "powrprof.dll") ||
			 strstr(lowername, "msvcr") == lowername ||
			 strstr(lowername, "msvcp") == lowername)
				return;

		// set module pointer if we are hooking exports from this module
		for(auto it=DllHooks.begin(); it != DllHooks.end(); ++it)
			if(!_stricmp(it->first.c_str(), modName))
				it->second.module = module;

		byte *baseAddress = (byte *)module;

		// the module could have been unloaded after our toolhelp snapshot, especially if we spent a long time
		// dealing with a previous module (like adding our hooks).
		wchar_t modpath[1024] = {0};
		GetModuleFileNameW(module, modpath, 1023);
		if(modpath[0] == 0) return;
		// increment the module reference count, so it doesn't disappear while we're processing it
		// there's a very small race condition here between if GetModuleFileName returns, the module is
		// unloaded then we load it again. The only way around that is inserting very scary locks between here
		// and FreeLibrary that I want to avoid. Worst case, we load a dll, hook it, then unload it again.
		HMODULE refcountModHandle = LoadLibraryW(modpath);

		PIMAGE_DOS_HEADER dosheader = (PIMAGE_DOS_HEADER)baseAddress;

		if(dosheader->e_magic != 0x5a4d)
		{
			RDCDEBUG("Ignoring module %s, since magic is 0x%04x not 0x%04x", modName, (uint32_t)dosheader->e_magic, 0x5a4dU);
			FreeLibrary(refcountModHandle);
			return;
		}

		char *PE00 = (char *)(baseAddress + dosheader->e_lfanew);
		PIMAGE_FILE_HEADER fileHeader = (PIMAGE_FILE_HEADER)(PE00+4);
		PIMAGE_OPTIONAL_HEADER optHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)fileHeader+sizeof(IMAGE_FILE_HEADER));

		DWORD iatSize = optHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
		DWORD iatOffset = optHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

		IMAGE_IMPORT_DESCRIPTOR *importDesc = (IMAGE_IMPORT_DESCRIPTOR *)(baseAddress + iatOffset);

		while(iatOffset && importDesc->FirstThunk)
		{
			const char *dllName = (const char *)(baseAddress + importDesc->Name);

			DllHookset *hookset = NULL;

			for(auto it=DllHooks.begin(); it != DllHooks.end(); ++it)
				if(!_stricmp(it->first.c_str(), dllName))
					hookset = &it->second;

			if(hookset && importDesc->OriginalFirstThunk > 0 && importDesc->FirstThunk > 0)
			{
				IMAGE_THUNK_DATA *origFirst = (IMAGE_THUNK_DATA *)(baseAddress + importDesc->OriginalFirstThunk);
				IMAGE_THUNK_DATA *first = (IMAGE_THUNK_DATA *)(baseAddress + importDesc->FirstThunk);

				while(origFirst->u1.AddressOfData)
				{
#ifdef WIN64
					if(origFirst->u1.AddressOfData & 0x8000000000000000)
#else
					if(origFirst->u1.AddressOfData & 0x80000000)
#endif
					{
						// low bits of origFirst->u1.AddressOfData contain an ordinal
						origFirst++;
						first++;
						continue;
					}

					IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(baseAddress + origFirst->u1.AddressOfData);
					void **IATentry = (void **)&first->u1.AddressOfData;

					struct hook_find
					{
						bool operator() (const FunctionHook &a, const char *b)
						{ return strcmp(a.function.c_str(), b) < 0; }
					};

					const char *importName = (const char *)import->Name;
					auto found = std::lower_bound(hookset->FunctionHooks.begin(), hookset->FunctionHooks.end(), importName, hook_find());

					if(found != hookset->FunctionHooks.end() && !strcmp(found->function.c_str(), importName) && found->excludeModule != module)
					{
						SCOPED_LOCK(lock);
						bool applied = found->ApplyHook(IATentry);

						if(!applied)
						{
							FreeLibrary(refcountModHandle);
							return;
						}
					}

					origFirst++;
					first++;
				}
			}

			importDesc++;
		}

		FreeLibrary(refcountModHandle);
	}
};

static CachedHookData *s_HookData = NULL;

static void HookAllModules()
{
	HANDLE hModuleSnap = INVALID_HANDLE_VALUE;

	// up to 10 retries
	for(int i=0; i < 10; i++)
	{
		hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());

		if(hModuleSnap == INVALID_HANDLE_VALUE)
		{
			DWORD err = GetLastError();

			RDCWARN("CreateToolhelp32Snapshot() -> 0x%08x", err);

			// retry if error is ERROR_BAD_LENGTH
			if(err == ERROR_BAD_LENGTH)
				continue;
		}

		// didn't retry, or succeeded
		break;
	}

	if(hModuleSnap == INVALID_HANDLE_VALUE)
	{
		RDCERR("Couldn't create toolhelp dump of modules in process");
		return;
	}

#ifdef UNICODE
#undef MODULEENTRY32
#undef Module32First
#undef Module32Next
#endif

  MODULEENTRY32 me32;
	RDCEraseEl(me32);
  me32.dwSize = sizeof(MODULEENTRY32);

	BOOL success = Module32First(hModuleSnap, &me32);

  if(success == FALSE)
  {
		DWORD err = GetLastError();

		RDCERR("Couldn't get first module in process: 0x%08x", err);
    CloseHandle(hModuleSnap);
		return;
  }

	uintptr_t ret = 0;

	int numModules = 0;

  do
  {
		s_HookData->ApplyHooks(me32.szModule, me32.hModule);
  } while(ret == 0 && Module32Next(hModuleSnap, &me32));

  CloseHandle(hModuleSnap);
}

HMODULE WINAPI Hooked_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE fileHandle, DWORD flags)
{
	// we can use the function naked, as when setting up the hook for LoadLibraryExA, our own module
	// was excluded from IAT patching
	HMODULE mod = LoadLibraryExA(lpLibFileName, fileHandle, flags);

	HookAllModules();

	return mod;
}

HMODULE WINAPI Hooked_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE fileHandle, DWORD flags)
{
	// we can use the function naked, as when setting up the hook for LoadLibraryExA, our own module
	// was excluded from IAT patching
	HMODULE mod = LoadLibraryExW(lpLibFileName, fileHandle, flags);

	HookAllModules();

	return mod;
}

HMODULE WINAPI Hooked_LoadLibraryA(LPCSTR lpLibFileName)
{
	return Hooked_LoadLibraryExA(lpLibFileName, NULL, 0);
}

HMODULE WINAPI Hooked_LoadLibraryW(LPCWSTR lpLibFileName)
{
	return Hooked_LoadLibraryExW(lpLibFileName, NULL, 0);
}

static bool OrdinalAsString(void *func)
{
	return uint64_t(func) <= 0xffff;
}

FARPROC WINAPI Hooked_GetProcAddress(HMODULE mod, LPCSTR func)
{
	if(mod == NULL || func == NULL)
		return (FARPROC)NULL;

	if(mod == s_HookData->module || OrdinalAsString((void *)func))
		return GetProcAddress(mod, func);

	for(auto it=s_HookData->DllHooks.begin(); it != s_HookData->DllHooks.end(); ++it)
	{
		if(it->second.module == NULL)
			it->second.module = GetModuleHandleA(it->first.c_str());

		if(mod == it->second.module)
		{
			FunctionHook search(func, NULL, NULL);

			auto found = std::lower_bound(it->second.FunctionHooks.begin(), it->second.FunctionHooks.end(), search);
			if(found != it->second.FunctionHooks.end() && !(search < *found))
			{
				if(found->origptr && *found->origptr == NULL)
					*found->origptr = (void *)GetProcAddress(mod, func);

				return (FARPROC)found->hookptr;
			}
		}
	}

	return GetProcAddress(mod, func);
}

void Win32_IAT_BeginHooks()
{
	s_HookData = new CachedHookData;
	RDCASSERT(s_HookData->DllHooks.empty());
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryA", NULL, &Hooked_LoadLibraryA));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryW", NULL, &Hooked_LoadLibraryW));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryExA", NULL, &Hooked_LoadLibraryExA));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("LoadLibraryExW", NULL, &Hooked_LoadLibraryExW));
	s_HookData->DllHooks["kernel32.dll"].FunctionHooks.push_back(FunctionHook("GetProcAddress", NULL, &Hooked_GetProcAddress));

	GetModuleHandleEx(
		GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
		(LPCTSTR)&s_HookData,
		&s_HookData->module);

	for(auto it=s_HookData->DllHooks.begin(); it != s_HookData->DllHooks.end(); ++it)
		for(size_t i=0; i < it->second.FunctionHooks.size(); i++)
			it->second.FunctionHooks[i].excludeModule = s_HookData->module;
}

// hook all functions for currently loaded modules.
// some of these hooks (as above) will hook LoadLibrary/GetProcAddress, to protect
void Win32_IAT_EndHooks()
{
	for(auto it=s_HookData->DllHooks.begin(); it != s_HookData->DllHooks.end(); ++it)
		std::sort(it->second.FunctionHooks.begin(), it->second.FunctionHooks.end());

	HookAllModules();
}

bool Win32_IAT_Hook(void **orig_function_ptr, const char *module_name, const char *function, void *destination_function_ptr)
{
	if(!_stricmp(module_name, "kernel32.dll"))
	{
		if(!strcmp(function, "LoadLibraryA") ||
			!strcmp(function, "LoadLibraryW") ||
			!strcmp(function, "LoadLibraryExA") ||
			!strcmp(function, "LoadLibraryExW") ||
			!strcmp(function, "GetProcAddress"))
		{
			RDCERR("Cannot hook LoadLibrary* or GetProcAddress, as these are hooked internally");
			return false;
		}
	}
	s_HookData->DllHooks[strlower(string(module_name))].FunctionHooks.push_back(FunctionHook(function, orig_function_ptr, destination_function_ptr));
	return true;
}
<|endoftext|>


<commit_before>
#include <QQmlContext>

#include <cppassist/cmdline/ArgumentParser.h>

#include <cppexpose/scripting/ScriptContext.h>
#include <cppexpose/reflection/Property.h>

#include <gloperate/gloperate.h>
#include <gloperate/gloperate-version.h>
#include <gloperate/base/Environment.h>

#include <gloperate-qt/base/GLContext.h>
#include <gloperate-qt/base/GLContextFactory.h>
#include <gloperate-qt/base/UpdateManager.h>

#include <gloperate-qtquick/QuickView.h>
#include <gloperate-qtquick/QmlEngine.h>
#include <gloperate-qtquick/QmlScriptContext.h>

#include "Config.h"
#include "Application.h"

using namespace gloperate;
using namespace gloperate_qt;
using namespace gloperate_qtquick;

int main(int argc, char * argv[])
{
    // Create gloperate environment
    Environment environment;

    // Initialize Qt application
    ::Application app(&environment, argc, argv);

    // Load configuration
    Config config(environment);

    // Configure update manager
    UpdateManager updateManager(&environment);

    // Create QML engine
    QmlEngine qmlEngine(&environment);
    qmlEngine.rootContext()->setContextProperty("config", &config);

    // Create scripting context backend
    environment.setupScripting(
        cppassist::make_unique<gloperate_qtquick::QmlScriptContext>(&qmlEngine)
    );

    // Configure and load plugins
    environment.componentManager()->addPluginPath(
        gloperate::pluginPath(), cppexpose::PluginPathType::Internal
    );
    environment.componentManager()->scanPlugins("loaders");
    environment.componentManager()->scanPlugins("stages");
    environment.componentManager()->scanPlugins("exporter");

    // Load and show QML
    auto window = cppassist::make_unique<QuickView>(&qmlEngine);
    // Specify desired context format
    cppassist::ArgumentParser argumentParser;
    argumentParser.parse(argc, argv);
    const auto contextString = argumentParser.value("--context");
    if(!contextString.empty())
    {
        gloperate::GLContextFormat format;
        if(!format.initializeFromString(contextString));
            return 1;
        QSurfaceFormat qFormat = gloperate_qt::GLContextFactory::toQSurfaceFormat(format);
        window->setFormat(qFormat);
    }
    window->setResizeMode(QQuickView::SizeRootObjectToView);
    window->setSource(QUrl::fromLocalFile(qmlEngine.gloperateModulePath() + "/Viewer.qml"));
    window->setGeometry(100, 100, 1280, 720);
    window->show();

    // Run main loop
    return app.exec();
}
<commit_msg>Remove erroneous semicolon<commit_after>
#include <QQmlContext>

#include <cppassist/cmdline/ArgumentParser.h>

#include <cppexpose/scripting/ScriptContext.h>
#include <cppexpose/reflection/Property.h>

#include <gloperate/gloperate.h>
#include <gloperate/gloperate-version.h>
#include <gloperate/base/Environment.h>

#include <gloperate-qt/base/GLContext.h>
#include <gloperate-qt/base/GLContextFactory.h>
#include <gloperate-qt/base/UpdateManager.h>

#include <gloperate-qtquick/QuickView.h>
#include <gloperate-qtquick/QmlEngine.h>
#include <gloperate-qtquick/QmlScriptContext.h>

#include "Config.h"
#include "Application.h"

using namespace gloperate;
using namespace gloperate_qt;
using namespace gloperate_qtquick;

int main(int argc, char * argv[])
{
    // Create gloperate environment
    Environment environment;

    // Initialize Qt application
    ::Application app(&environment, argc, argv);

    // Load configuration
    Config config(environment);

    // Configure update manager
    UpdateManager updateManager(&environment);

    // Create QML engine
    QmlEngine qmlEngine(&environment);
    qmlEngine.rootContext()->setContextProperty("config", &config);

    // Create scripting context backend
    environment.setupScripting(
        cppassist::make_unique<gloperate_qtquick::QmlScriptContext>(&qmlEngine)
    );

    // Configure and load plugins
    environment.componentManager()->addPluginPath(
        gloperate::pluginPath(), cppexpose::PluginPathType::Internal
    );
    environment.componentManager()->scanPlugins("loaders");
    environment.componentManager()->scanPlugins("stages");
    environment.componentManager()->scanPlugins("exporter");

    // Load and show QML
    auto window = cppassist::make_unique<QuickView>(&qmlEngine);
    // Specify desired context format
    cppassist::ArgumentParser argumentParser;
    argumentParser.parse(argc, argv);
    const auto contextString = argumentParser.value("--context");
    if(!contextString.empty())
    {
        gloperate::GLContextFormat format;
        if(!format.initializeFromString(contextString))
            return 1;
        QSurfaceFormat qFormat = gloperate_qt::GLContextFactory::toQSurfaceFormat(format);
        window->setFormat(qFormat);
    }
    window->setResizeMode(QQuickView::SizeRootObjectToView);
    window->setSource(QUrl::fromLocalFile(qmlEngine.gloperateModulePath() + "/Viewer.qml"));
    window->setGeometry(100, 100, 1280, 720);
    window->show();

    // Run main loop
    return app.exec();
}
<|endoftext|>


<commit_before>#include "ChOgreGUIManager.h"

namespace ChOgre {

	ChOgreGUIManager::_KeyCallback::_KeyCallback(MyGUI::Gui** GUI) {
		m_ppGUI = GUI;
	}

	void ChOgreGUIManager::_KeyCallback::call(scancode_t ScanCode, keycode_t KeyCode, const ChOgreKeyState& KeyState) {
		if (KeyState.down) {
			//MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode), SDL_GetKeyName(KeyCode)[0]);
			(*m_ppGUI)->injectKeyPress(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode), SDL_GetKeyName(KeyCode)[0]);
		}
		if (!KeyState.down) {
			//MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode));
			(*m_ppGUI)->injectKeyRelease(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode));
		}
	}

	ChOgreGUIManager::_MouseCallback::_MouseCallback(MyGUI::Gui** GUI) {
		m_ppGUI = GUI;
	}

	void ChOgreGUIManager::_MouseCallback::call(const ChOgreMouseState& MouseState) {
		//MyGUI::InputManager::getInstance().injectMouseMove(MouseState.position.x, MouseState.position.y, MouseState.wheel.y);
		(*m_ppGUI)->injectMouseMove(MouseState.position.x, MouseState.position.y, MouseState.wheel.y);

		if (MouseState.left.down) {
			//MyGUI::InputManager::getInstance().injectMousePress(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Left);
			(*m_ppGUI)->injectMousePress(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Left);
		}
		else if (!MouseState.left.down) {
			//MyGUI::InputManager::getInstance().injectMouseRelease(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Left);
			(*m_ppGUI)->injectMouseRelease(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Left);
		}
		if (MouseState.right.down) {
			//MyGUI::InputManager::getInstance().injectMousePress(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Right);
			(*m_ppGUI)->injectMousePress(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Right);
		}
		else if (!MouseState.right.down) {
			//MyGUI::InputManager::getInstance().injectMouseRelease(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Right);
			(*m_ppGUI)->injectMouseRelease(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Right);
		}
		if (MouseState.middle.down) {
			//MyGUI::InputManager::getInstance().injectMousePress(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Middle);
			(*m_ppGUI)->injectMousePress(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Middle);
		}
		else if (!MouseState.middle.down) {
			//MyGUI::InputManager::getInstance().injectMouseRelease(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Middle);
			(*m_ppGUI)->injectMouseRelease(MouseState.position.x, MouseState.position.y, MyGUI::MouseButton::Middle);
		}
	}

	ChOgreGUIManager::_WindowCallback::_WindowCallback(Ogre::RenderWindow* RenderWindow) {
		m_pRenderWindow = RenderWindow;
	}

	void ChOgreGUIManager::_WindowCallback::call() {
		MyGUI::LayerManager::getInstance().resizeView(MyGUI::IntSize(m_pRenderWindow->getWidth(), m_pRenderWindow->getHeight()));
	}

	ChOgreGUIManager::ChOgreGUIManager(Ogre::RenderWindow* RenderWindow, Ogre::SceneManager* SceneManager, ChOgre_SDLInputHandler* InputManager) : m_keyboard(&m_pGUI), m_mouse(&m_pGUI), m_window(RenderWindow) {
		m_pInputManager = InputManager;
		m_pSceneManager = SceneManager;
		m_pRenderWindow = RenderWindow;

		m_pPlatform = new MyGUI::OgrePlatform();
		m_pPlatform->initialise(m_pRenderWindow, m_pSceneManager);
		m_pGUI = new MyGUI::Gui();
		m_pGUI->initialise();

		MyGUI::LayerManager::getInstance().resizeView(MyGUI::IntSize(RenderWindow->getWidth(), RenderWindow->getHeight()));

		m_pInputManager->addCallback(m_keyboard);
		m_pInputManager->addCallback(m_mouse);
	}

	ChOgreGUIManager::~ChOgreGUIManager() {
		m_pGUI->shutdown();
		delete m_pGUI;
		m_pPlatform->shutdown();
		delete m_pPlatform;
	}

	void ChOgreGUIManager::setVisible(bool Visible) {
		m_isVisible = Visible;
	}

}<commit_msg>Fixed the problem where the cursor didn't move<commit_after>#include "ChOgreGUIManager.h"

namespace ChOgre {

	ChOgreGUIManager::_KeyCallback::_KeyCallback(MyGUI::Gui** GUI) {
		m_ppGUI = GUI;
	}

	void ChOgreGUIManager::_KeyCallback::call(scancode_t ScanCode, keycode_t KeyCode, const ChOgreKeyState& KeyState) {
		if (KeyState.down) {
			//MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode), SDL_GetKeyName(KeyCode)[0]);
			(*m_ppGUI)->injectKeyPress(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode), SDL_GetKeyName(KeyCode)[0]);
		}
		if (!KeyState.down) {
			//MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode));
			(*m_ppGUI)->injectKeyRelease(MyGUI::KeyCode((MyGUI::KeyCode::Enum)ScanCode));
		}
	}

	ChOgreGUIManager::_MouseCallback::_MouseCallback(MyGUI::Gui** GUI) {
		m_ppGUI = GUI;
	}

	void ChOgreGUIManager::_MouseCallback::call(const ChOgreMouseState& MouseState) {
		float _x = MouseState.position.x * (*m_ppGUI)->getViewWidth();
		float _y = MouseState.position.y * (*m_ppGUI)->getViewHeight();

		MyGUI::InputManager::getInstance().injectMouseMove(_x, _y, MouseState.wheel.y);
		//(*m_ppGUI)->injectMouseMove(MouseState.position.x, MouseState.position.y, MouseState.wheel.y);
		MyGUI::PointerManager::getInstance().getDefaultPointer();

		if (MouseState.left.down) {
			MyGUI::InputManager::getInstance().injectMousePress(_x, _y, MyGUI::MouseButton::Left);
		}
		else if (!MouseState.left.down) {
			MyGUI::InputManager::getInstance().injectMouseRelease(_x, _y, MyGUI::MouseButton::Left);
		}
		if (MouseState.right.down) {
			MyGUI::InputManager::getInstance().injectMousePress(_x, _y, MyGUI::MouseButton::Right);
		}
		else if (!MouseState.right.down) {
			MyGUI::InputManager::getInstance().injectMouseRelease(_x, _y, MyGUI::MouseButton::Right);
		}
		if (MouseState.middle.down) {
			MyGUI::InputManager::getInstance().injectMousePress(_x, _y, MyGUI::MouseButton::Middle);
		}
		else if (!MouseState.middle.down) {
			MyGUI::InputManager::getInstance().injectMouseRelease(_x, _y, MyGUI::MouseButton::Middle);
		}
	}

	ChOgreGUIManager::_WindowCallback::_WindowCallback(Ogre::RenderWindow* RenderWindow) {
		m_pRenderWindow = RenderWindow;
	}

	void ChOgreGUIManager::_WindowCallback::call() {
		MyGUI::LayerManager::getInstance().resizeView(MyGUI::IntSize(m_pRenderWindow->getWidth(), m_pRenderWindow->getHeight()));
	}

	ChOgreGUIManager::ChOgreGUIManager(Ogre::RenderWindow* RenderWindow, Ogre::SceneManager* SceneManager, ChOgre_SDLInputHandler* InputManager) : m_keyboard(&m_pGUI), m_mouse(&m_pGUI), m_window(RenderWindow) {
		m_pInputManager = InputManager;
		m_pSceneManager = SceneManager;
		m_pRenderWindow = RenderWindow;

		m_pPlatform = new MyGUI::OgrePlatform();
		m_pPlatform->initialise(m_pRenderWindow, m_pSceneManager);
		m_pGUI = new MyGUI::Gui();
		m_pGUI->initialise();

		m_pGUI->hidePointer();

		MyGUI::LayerManager::getInstance().resizeView(MyGUI::IntSize(RenderWindow->getWidth(), RenderWindow->getHeight()));

		m_pInputManager->addCallback(m_keyboard);
		m_pInputManager->addCallback(m_mouse);
	}

	ChOgreGUIManager::~ChOgreGUIManager() {
		m_pGUI->shutdown();
		delete m_pGUI;
		m_pPlatform->shutdown();
		delete m_pPlatform;
	}

	void ChOgreGUIManager::setVisible(bool Visible) {
		m_isVisible = Visible;
	}

}<|endoftext|>


<commit_before>#include <tetra/TicTocClock.hpp>

#include <algorithm>
#include <iostream>
#include <list>

using namespace std;
using namespace tetra;

class Behavior;
class BehaviorList;
using OwnedBehavior = std::unique_ptr<Behavior>;

/**
 * A behavior is a chunk of code which executes in a BehaviorList.
 * Behaviors are provided a pointer to their parent list before their
 * onStart method is first called.
 */
class Behavior
{
public:
    bool complete = false;
    bool blocking = false;
    BehaviorList* parentList;

    virtual void run(double dt) = 0;
    virtual void onStart();
    virtual void onEnd();

    Behavior* insertInFrontOfMe(OwnedBehavior&& ownedBehavior);
};

void Behavior::onStart() {}
void Behavior::onEnd() {}

/**
 * The BehaviorList is a collection of behaviors which are executed each time
 * run() is invoked.
 */
class BehaviorList
{
public:
    /**
     * Insert the owned behavior before the here pointer.
     * If the 'here' pointer cannot be found then the behavior is inserted at the
     * end of the list.
     */
    Behavior* insertBefore(const Behavior* here, OwnedBehavior&& action);

    /**
     * Insert the owned behavior after the 'here' pointer.
     * If the 'here' pointer cannot be found in the behavior list then the provided
     * behavior is inserted at the end of the list.
     */
    Behavior* insertAfter(const Behavior* here, OwnedBehavior&& action);

    /**
     * Push the provided behavior onto the front of the behavior list.
     */
    Behavior* pushFront(OwnedBehavior&& action);

    /**
     * Execute the behaviors in the behavior list, stopping at the end of the list
     * or after the first blocking Behavior executes.
     */
    void run(double dt);

    /**
     * Returns true as long as there are any behaviors which have not completed.
     */
    bool running() const;
private:
    using BehaviorCollection = std::list<OwnedBehavior>;
    BehaviorCollection behaviors;

    /**
     * Insert the action at a location, set the parentList, and call onStart.
     */
    Behavior* insertAt(BehaviorCollection::iterator location, OwnedBehavior&& action);
};

Behavior*
Behavior::insertInFrontOfMe(OwnedBehavior&& ownedBehavior)
{
    return this->parentList->insertBefore(this, move(ownedBehavior));
}

class Delay : public Behavior
{
public:
    Delay(double duration);

    virtual void run(double dt) override;

    static unique_ptr<Delay> forSeconds(double duration);
private:
    const double duration;
    double elapsed;
};

Delay::Delay(double duration)
    : duration{duration}
    , elapsed{0.0f}
{
    this->blocking = true;
}

void
Delay::run(double dt)
{
    elapsed += dt;
    if (elapsed >= duration)
    {
        this->complete = true;
    }
}

unique_ptr<Delay>
Delay::forSeconds(double duration)
{
    return unique_ptr<Delay>{new Delay{duration}};
}

class Echo : public Behavior
{
public:
    Echo(const std::string& msg);

    virtual void run(double dt) override;

    template <class T>
    static unique_ptr<Echo> message(const T& msg)
    {
        using std::to_string;
        return unique_ptr<Echo>{new Echo{to_string(msg)}};
    }

    static unique_ptr<Echo> message(const char* msg);
private:
    const std::string msg;
};

Echo::Echo(const std::string& msg)
    : msg{msg}
{ }

void
Echo::run(double dt)
{
    cout << msg << endl;
    this->complete = true;
}

unique_ptr<Echo>
Echo::message(const char* msg)
{
    return unique_ptr<Echo>{new Echo{string{msg}}};
}

class MyTurboBehavior : public Behavior
{
public:

    virtual void run(double dt) override
    {
        if (count == 0)
        {
            this->complete = true;
            return;
        }

        this->insertInFrontOfMe(Echo::message("HEHEHEHEHE"));
        this->insertInFrontOfMe(Delay::forSeconds(1.0));
        this->insertInFrontOfMe(Echo::message(count));
        count -= 1;
    }

    static unique_ptr<MyTurboBehavior> turbo()
    {
        return unique_ptr<MyTurboBehavior>{new MyTurboBehavior{}};
    }
private:
    int count = 5;
};

int main()
{
    HighResTicToc timer{};

    auto mylist = BehaviorList{};
    mylist.pushFront(MyTurboBehavior::turbo());

    while(mylist.running())
    {
        mylist.run(timer.ticToc());
    }
    return 0;
}

Behavior*
BehaviorList::insertBefore(const Behavior* here, OwnedBehavior&& action)
{
    auto insertIter = find_if(begin(this->behaviors), end(this->behaviors),
                              [&here](const OwnedBehavior& action)
                              {
                                  return action.get() == here;
                              });
    return this->insertAt(insertIter, move(action));
}

Behavior*
BehaviorList::insertAfter(const Behavior* here, OwnedBehavior&& action)
{
    auto insertIter = find_if(begin(this->behaviors), end(this->behaviors),
                              [&here](const OwnedBehavior& action)
                              {
                                  return action.get() == here;
                              });
    if (insertIter != end(this->behaviors))
    {
        insertIter++;
    }
    return this->insertAt(insertIter, move(action));
}

Behavior*
BehaviorList::pushFront(OwnedBehavior&& action)
{
    return insertAt(begin(this->behaviors), move(action));
}

Behavior*
BehaviorList::insertAt(BehaviorCollection::iterator location, OwnedBehavior&& action)
{
    auto insertedIter = this->behaviors.insert(location, move(action));
    auto actionPtr = insertedIter->get();
    actionPtr->parentList = this;
    actionPtr->onStart();
    return actionPtr;
}

void
BehaviorList::run(double dt)
{
    // For loop is stable even if behaviors insert elements because
    // std::list iterators are not invalidated when elements are inserted.
    // all removal happens after the update loop
    for (const auto& behavior : this->behaviors)
    {
        // don't allow a completed behavior to run or block others
        if (behavior->complete)
        {
            continue;
        }

        behavior->run(dt);
        if (behavior->blocking)
        {
            break;
        }
    }

    // move completed actions to the end of the list (note that stable partition
    // preserves relative ordering of behaviors)
    auto startOfCompleted =
        stable_partition(begin(this->behaviors), end(this->behaviors),
                         [](const OwnedBehavior& action)
                         {
                             return !action->complete;
                         });
    // run onEnd for completed actions
    for_each(startOfCompleted, end(this->behaviors), [](const OwnedBehavior& action)
    {
        action->onEnd();
    });
    // erase the ended actions
    this->behaviors.erase(startOfCompleted, end(this->behaviors));
}

bool
BehaviorList::running() const
{
    return !this->behaviors.empty();
}

<commit_msg>add some comments to actionlist sketch<commit_after>#include <tetra/TicTocClock.hpp>

#include <algorithm>
#include <iostream>
#include <list>

using namespace std;
using namespace tetra;

class Behavior;
class BehaviorList;
using OwnedBehavior = std::unique_ptr<Behavior>;

/**
 * A behavior is a chunk of code which executes in a BehaviorList.
 * Behaviors are provided a pointer to their parent list before their
 * onStart method is first called.
 */
class Behavior
{
public:
    bool complete = false;
    bool blocking = false;
    BehaviorList* parentList;

    virtual void run(double dt) = 0;
    virtual void onStart();
    virtual void onEnd();

    Behavior* insertInFrontOfMe(OwnedBehavior&& ownedBehavior);
};

void Behavior::onStart() {}
void Behavior::onEnd() {}

/**
 * The BehaviorList is a collection of behaviors which are executed each time
 * run() is invoked.
 */
class BehaviorList
{
public:
    /**
     * Insert the owned behavior before the here pointer.
     * If the 'here' pointer cannot be found then the behavior is inserted at the
     * end of the list.
     */
    Behavior* insertBefore(const Behavior* here, OwnedBehavior&& action);

    /**
     * Insert the owned behavior after the 'here' pointer.
     * If the 'here' pointer cannot be found in the behavior list then the provided
     * behavior is inserted at the end of the list.
     */
    Behavior* insertAfter(const Behavior* here, OwnedBehavior&& action);

    /**
     * Push the provided behavior onto the front of the behavior list.
     */
    Behavior* pushFront(OwnedBehavior&& action);

    /**
     * Execute the behaviors in the behavior list, stopping at the end of the list
     * or after the first blocking Behavior executes.
     */
    void run(double dt);

    /**
     * Returns true as long as there are any behaviors which have not completed.
     */
    bool running() const;
private:
    using BehaviorCollection = std::list<OwnedBehavior>;
    BehaviorCollection behaviors;

    /**
     * Insert the action at a location, set the parentList, and call onStart.
     */
    Behavior* insertAt(BehaviorCollection::iterator location, OwnedBehavior&& action);
};

Behavior*
Behavior::insertInFrontOfMe(OwnedBehavior&& ownedBehavior)
{
    return this->parentList->insertBefore(this, move(ownedBehavior));
}

class Delay : public Behavior
{
public:
    Delay(double duration);

    virtual void run(double dt) override;

    static unique_ptr<Delay> forSeconds(double duration);
private:
    const double duration;
    double elapsed;
};

Delay::Delay(double duration)
    : duration{duration}
    , elapsed{0.0f}
{
    this->blocking = true;
}

void
Delay::run(double dt)
{
    elapsed += dt;
    if (elapsed >= duration)
    {
        this->complete = true;
    }
}

unique_ptr<Delay>
Delay::forSeconds(double duration)
{
    return unique_ptr<Delay>{new Delay{duration}};
}

class Echo : public Behavior
{
public:
    Echo(const std::string& msg);

    virtual void run(double dt) override;

    static unique_ptr<Echo> message(const string& msg);
private:
    const std::string msg;
};

unique_ptr<Echo>
Echo::message(const string& msg)
{
    return unique_ptr<Echo>{new Echo{msg}};
}

Echo::Echo(const std::string& msg)
    : msg{msg}
{ }

void
Echo::run(double dt)
{
    cout << msg << endl;
    this->complete = true;
}

class MyTurboBehavior : public Behavior
{
public:
    virtual void onStart() override
    {
        cout << " -> starting my turbo behavior" << "\n"
             << " -> So pretend to gather some resources or something"
             << endl;
    }

    virtual void onEnd() override
    {
        cout << " -> ending my turbo behavior" << "\n"
             << " -> so pretend to clean things up or something"
             << endl;
    }

    virtual void run(double dt) override
    {
        cout << " -> count is " << this->count << " wait 1 second" << endl;

        this->insertInFrontOfMe(Delay::forSeconds(1.0));
        this->insertInFrontOfMe(
            Echo::message("finished delay for count " + to_string(this->count))
        );
        this->count -= 1;

        if (this->count == 0)
        {
            this->complete = true;
            return;
        }
    }

    static unique_ptr<MyTurboBehavior> turbo()
    {
        return unique_ptr<MyTurboBehavior>{new MyTurboBehavior{}};
    }
private:
    int count = 5;
};

int main()
{
    // Lets use this to track the total execution time
    auto totalTimer = HighResTicToc{};

    // Lets use this for tracking time per frame
    auto timer = HighResTicToc{};

    // Create the behavior list and push my turbo action into it
    auto mylist = BehaviorList{};
    mylist.pushFront(MyTurboBehavior::turbo());

    while(mylist.running())
    {
        mylist.run(timer.ticToc());
    }

    cout << "completed in " << totalTimer.toc() << " seconds" << endl;
    /*
     * Did you notice that the total time is _more_ than 5 seconds?!
     * This is actually not incorrect behavior, there are two factors at play here:
     *
     * 1 - The delay is inserted by my turbo behavior _before_ itself.
     *     This means that the delay only starts burning down on the next frame.
     *     This means that a delay of 1 second which is created this frame, will
     *     actually end 1 second + ~16 milliseconds from now.
     *     The behavior is expected -- once the delay starts ticking it expires
     *     after 1 second.
     *
     * 2 - The c++ standard this_thread::sleep_for is used inside of the TicTocClock
     *     to sleep if the min duration hasn't been met.
     *     The sleep_for method is allowed to be somewhat inprecise and sleep for
     *     longer than requested. So depending on the std lib implementation and
     *     the underlying OS there is a bit of room for variablility.
     */
    return 0;
}

Behavior*
BehaviorList::insertBefore(const Behavior* here, OwnedBehavior&& action)
{
    auto insertIter = find_if(begin(this->behaviors), end(this->behaviors),
                              [&here](const OwnedBehavior& action)
                              {
                                  return action.get() == here;
                              });
    return this->insertAt(insertIter, move(action));
}

Behavior*
BehaviorList::insertAfter(const Behavior* here, OwnedBehavior&& action)
{
    auto insertIter = find_if(begin(this->behaviors), end(this->behaviors),
                              [&here](const OwnedBehavior& action)
                              {
                                  return action.get() == here;
                              });
    if (insertIter != end(this->behaviors))
    {
        insertIter++;
    }
    return this->insertAt(insertIter, move(action));
}

Behavior*
BehaviorList::pushFront(OwnedBehavior&& action)
{
    return insertAt(begin(this->behaviors), move(action));
}

Behavior*
BehaviorList::insertAt(BehaviorCollection::iterator location, OwnedBehavior&& action)
{
    auto insertedIter = this->behaviors.insert(location, move(action));
    auto actionPtr = insertedIter->get();
    actionPtr->parentList = this;
    actionPtr->onStart();
    return actionPtr;
}

void
BehaviorList::run(double dt)
{
    // For loop is stable even if behaviors insert elements because
    // std::list iterators are not invalidated when elements are inserted.
    // all removal happens after the update loop
    for (const auto& behavior : this->behaviors)
    {
        // don't allow a completed behavior to run or block others
        if (behavior->complete)
        {
            continue;
        }

        behavior->run(dt);
        if (behavior->blocking)
        {
            break;
        }
    }

    // move completed actions to the end of the list (note that stable partition
    // preserves relative ordering of behaviors)
    auto startOfCompleted =
        stable_partition(begin(this->behaviors), end(this->behaviors),
                         [](const OwnedBehavior& action)
                         {
                             return !action->complete;
                         });
    // run onEnd for completed actions
    for_each(startOfCompleted, end(this->behaviors), [](const OwnedBehavior& action)
    {
        action->onEnd();
    });
    // erase the ended actions
    this->behaviors.erase(startOfCompleted, end(this->behaviors));
}

bool
BehaviorList::running() const
{
    return !this->behaviors.empty();
}

<|endoftext|>


<commit_before><commit_msg>camera example<commit_after><|endoftext|>


<commit_before>#include <math.h>
#include <wiring.h>
#include "grillpid.h"

// The temperatures are averaged over 1, 2, 4 or 8 samples
// Set this define to log2(samples) to adjust the number of samples
#define TEMP_AVG_COUNT_LOG2 3

// The minimum fan speed (%) that activates the "long pulse" mode
#define MINIMUM_FAN_SPEED 10

#define TEMPPROBE_AVG_SMOOTH (1.0f/30.0f)
#define FANSPEED_AVG_SMOOTH (1.0f/120.0f)

void calcExpMovingAverage(const float smooth, float *currAverage, float newValue)
{
  if (*currAverage == -1.0f)
    *currAverage = newValue;
  else
  {
    newValue = newValue - *currAverage;
    *currAverage = *currAverage + (smooth * newValue);
  }
}

void ProbeAlarm::updateStatus(int value)
{
  if (Status & HIGH_ENABLED != 0)
    if (value >= _high)
      Status |= HIGH_RINGING;
    else
      Status &= ~(HIGH_RINGING | HIGH_SILENCED);

  if (Status & LOW_ENABLED != 0)
    if (value <= _low)
      Status |= LOW_RINGING;
    else
      Status &= ~(LOW_RINGING | LOW_SILENCED);
}

void ProbeAlarm::setHigh(int value)
{
  _high = value;
  Status &= ~(HIGH_ENABLED | HIGH_RINGING | HIGH_SILENCED);
  if (value)
    Status |= HIGH_ENABLED;
}

void ProbeAlarm::setLow(int value)
{
  _low = value;
  Status &= ~(LOW_ENABLED | LOW_RINGING | LOW_SILENCED);
  if (value)
    Status |= LOW_ENABLED;
}

inline void TempProbe::readTemp(void)
{
  unsigned int analog_temp = analogRead(_pin);
  _accumulator += analog_temp;
}

inline void TempProbe::calcTemp(void)
{
  const float Rknown = 22000.0f;
  const float Vin = 1023.0f;

  unsigned int Vout = _accumulator >> TEMP_AVG_COUNT_LOG2;
  _accumulator = 0;

  if ((Vout == 0) || (Vout >= (unsigned int)Vin))
  {
    Temperature = 0.0f;
    return;
  }
  else
  {
    float R, T;
    // If you put the fixed resistor on the Vcc side of the thermistor, use the following
    R = log(Rknown / ((Vin / (float)Vout) - 1.0f));
    // If you put the thermistor on the Vcc side of the fixed resistor use the following
    // R = log(Rknown * Vin / (float)Vout - Rknown);

    // Compute degrees K
    T = 1.0f / ((_steinhart->C * R * R + _steinhart->B) * R + _steinhart->A);

    // return degrees F
    Temperature = ((T - 273.15f) * (9.0f / 5.0f)) + 32.0f;
    // Sanity - anything less than 0F or greater than 999F is rejected
    if (Temperature < 0.0f || Temperature > 999.0f)
      Temperature = 0.0f;

    if (Temperature != 0.0f)
    {
      Temperature += Offset;
      calcExpMovingAverage(TEMPPROBE_AVG_SMOOTH, &TemperatureAvg, Temperature);
      Alarms.updateStatus(Temperature);
    }
  }
}

/* Calucluate the desired fan speed using the proportional–integral-derivative (PID) controller algorithm */
inline void GrillPid::calcFanSpeed(TempProbe *controlProbe)
{
  unsigned char lastFanSpeed = _fanSpeed;
  _fanSpeed = 0;

  float currentTemp = controlProbe->Temperature;
  // If the pit probe is registering 0 degrees, don't jack the fan up to MAX
  if (currentTemp == 0.0f)
    return;
  // If we're in lid open mode, fan should be off
  if (LidOpenResumeCountdown != 0)
    return;

  float error;
  error = _setPoint - currentTemp;

  // anti-windup: Make sure we only adjust the I term while
  // inside the proportional control range
  if ((error > 0 && lastFanSpeed < MaxFanSpeed) ||
      (error < 0 && lastFanSpeed > 0))
    _pidErrorSum += (error * Pid[PIDI]);

  // the B and P terms are in 0-100 scale, but the I and D terms are dependent on degrees
  float averageTemp = controlProbe->TemperatureAvg;
  int control
    = Pid[PIDB] + Pid[PIDP] * (error + _pidErrorSum - (Pid[PIDD] * (currentTemp - averageTemp)));

  if (control >= MaxFanSpeed)
    _fanSpeed = MaxFanSpeed;
  else if (control > 0)
    _fanSpeed = control;
}

void GrillPid::commitFanSpeed(void)
{
  calcExpMovingAverage(FANSPEED_AVG_SMOOTH, &FanSpeedAvg, _fanSpeed);

  /* For anything above MINIMUM_FAN_SPEED, do a nomal PWM write.
     For below MINIMUM_FAN_SPEED we use a "long pulse PWM", where
     the pulse is 10 seconds in length.  For each percent we are
     emulating, run the fan for one interval. */
  if (_fanSpeed >= MINIMUM_FAN_SPEED)
  {
    analogWrite(_blowerPin, _fanSpeed * 255 / 100);
    _longPwmTmr = 0;
  }
  else
  {
    // Simple PWM, ON for first [FanSpeed] intervals then OFF
    // for the remainder of the period
    unsigned char pwmVal;
    pwmVal = (_fanSpeed > _longPwmTmr) ? 255/MINIMUM_FAN_SPEED : 0;

    analogWrite(_blowerPin, pwmVal);
    // Long PWM period is 10 intervals
    if (++_longPwmTmr > 9)
      _longPwmTmr = 0;
  }  /* long PWM */
}

boolean GrillPid::isAnyFoodProbeActive(void)
{
  unsigned char i;
  for (i=TEMP_FOOD1; i<TEMP_COUNT; i++)
    if (Probes[i]->Temperature != 0.0f)
      return true;

  return false;
}

void GrillPid::resetLidOpenResumeCountdown(void)
{
  LidOpenResumeCountdown = LidOpenDuration;
  _pitTemperatureReached = false;
}

void GrillPid::setSetPoint(int value)
{
  _setPoint = value;
  _pitTemperatureReached = false;
  _manualFanMode = false;
  _pidErrorSum = 0;
}

void GrillPid::setFanSpeed(int value)
{
  _manualFanMode = true;
  if (value < 0)
    _fanSpeed = 0;
  else if (value > 100)
    _fanSpeed = 100;
  else
    _fanSpeed = value;
}

boolean GrillPid::doWork(void)
{
  unsigned long m = millis();
  if ((m - _lastTempRead) < (1000 >> TEMP_AVG_COUNT_LOG2))
    return false;
  _lastTempRead = m;

  unsigned char i;
  for (i=0; i<TEMP_COUNT; i++)
    Probes[i]->readTemp();

  if (++_accumulatedCount < (1 << TEMP_AVG_COUNT_LOG2))
    return false;

  for (i=0; i<TEMP_COUNT; i++)
    Probes[i]->calcTemp();

  if (!_manualFanMode)
  {
    // Always calculate the fan speed
    // calFanSpeed() will bail if it isn't supposed to be in control
    TempProbe *probePit = Probes[TEMP_PIT];
    calcFanSpeed(probePit);

    int pitTemp = probePit->Temperature;
    if (pitTemp >= _setPoint)
    {
      // When we first achieve temperature, reset any P sum we accumulated during startup
      // If we actually neded that sum to achieve temperature we'll rebuild it, and it
      // prevents bouncing around above the temperature when you first start up
      if (!_pitTemperatureReached)
      {
        _pitTemperatureReached = true;
        _pidErrorSum = 0.0f;
      }
      LidOpenResumeCountdown = 0;
    }
    else if (LidOpenResumeCountdown != 0)
    {
      --LidOpenResumeCountdown;
    }
    // If the pit temperature dropped has more than [lidOpenOffset] degrees
    // after reaching temp, and the fan has not been running more than 90% of
    // the average period. note that the code assumes g_LidOpenResumeCountdown <= 0
    else if (_pitTemperatureReached && ((_setPoint - pitTemp) > (int)LidOpenOffset) && FanSpeedAvg < 90.0f)
    {
      resetLidOpenResumeCountdown();
    }
  }   /* if !manualFanMode */
  commitFanSpeed();

  _accumulatedCount = 0;
  return true;
}

<commit_msg>Replace TEMP_AVG_COUNT_LOG2 with TEMP_AVG_COUNT.  The old LOG2 optimization was removed long ago and this makes the code more clear<commit_after>#include <math.h>
#include <wiring.h>
#include "grillpid.h"

// The temperatures are averaged over 1, 2, 4 or 8 samples
#define TEMP_AVG_COUNT 8

// The minimum fan speed (%) that activates the "long pulse" mode
#define MINIMUM_FAN_SPEED 10

#define TEMPPROBE_AVG_SMOOTH (1.0f/30.0f)
#define FANSPEED_AVG_SMOOTH (1.0f/120.0f)

void calcExpMovingAverage(const float smooth, float *currAverage, float newValue)
{
  if (*currAverage == -1.0f)
    *currAverage = newValue;
  else
  {
    newValue = newValue - *currAverage;
    *currAverage = *currAverage + (smooth * newValue);
  }
}

void ProbeAlarm::updateStatus(int value)
{
  if (Status & HIGH_ENABLED != 0)
    if (value >= _high)
      Status |= HIGH_RINGING;
    else
      Status &= ~(HIGH_RINGING | HIGH_SILENCED);

  if (Status & LOW_ENABLED != 0)
    if (value <= _low)
      Status |= LOW_RINGING;
    else
      Status &= ~(LOW_RINGING | LOW_SILENCED);
}

void ProbeAlarm::setHigh(int value)
{
  _high = value;
  Status &= ~(HIGH_ENABLED | HIGH_RINGING | HIGH_SILENCED);
  if (value)
    Status |= HIGH_ENABLED;
}

void ProbeAlarm::setLow(int value)
{
  _low = value;
  Status &= ~(LOW_ENABLED | LOW_RINGING | LOW_SILENCED);
  if (value)
    Status |= LOW_ENABLED;
}

inline void TempProbe::readTemp(void)
{
  unsigned int analog_temp = analogRead(_pin);
  _accumulator += analog_temp;
}

inline void TempProbe::calcTemp(void)
{
  const float Rknown = 22000.0f;
  const float Vin = 1023.0f;

  unsigned int Vout = _accumulator / TEMP_AVG_COUNT;
  _accumulator = 0;

  if ((Vout == 0) || (Vout >= (unsigned int)Vin))
  {
    Temperature = 0.0f;
    return;
  }
  else
  {
    float R, T;
    // If you put the fixed resistor on the Vcc side of the thermistor, use the following
    R = log(Rknown / ((Vin / (float)Vout) - 1.0f));
    // If you put the thermistor on the Vcc side of the fixed resistor use the following
    // R = log(Rknown * Vin / (float)Vout - Rknown);

    // Compute degrees K
    T = 1.0f / ((_steinhart->C * R * R + _steinhart->B) * R + _steinhart->A);

    // return degrees F
    Temperature = ((T - 273.15f) * (9.0f / 5.0f)) + 32.0f;
    // Sanity - anything less than 0F or greater than 999F is rejected
    if (Temperature < 0.0f || Temperature > 999.0f)
      Temperature = 0.0f;

    if (Temperature != 0.0f)
    {
      Temperature += Offset;
      calcExpMovingAverage(TEMPPROBE_AVG_SMOOTH, &TemperatureAvg, Temperature);
      Alarms.updateStatus(Temperature);
    }
  }
}

/* Calucluate the desired fan speed using the proportional–integral-derivative (PID) controller algorithm */
inline void GrillPid::calcFanSpeed(TempProbe *controlProbe)
{
  unsigned char lastFanSpeed = _fanSpeed;
  _fanSpeed = 0;

  float currentTemp = controlProbe->Temperature;
  // If the pit probe is registering 0 degrees, don't jack the fan up to MAX
  if (currentTemp == 0.0f)
    return;
  // If we're in lid open mode, fan should be off
  if (LidOpenResumeCountdown != 0)
    return;

  float error;
  error = _setPoint - currentTemp;

  // anti-windup: Make sure we only adjust the I term while
  // inside the proportional control range
  if ((error > 0 && lastFanSpeed < MaxFanSpeed) ||
      (error < 0 && lastFanSpeed > 0))
    _pidErrorSum += (error * Pid[PIDI]);

  // the B and P terms are in 0-100 scale, but the I and D terms are dependent on degrees
  float averageTemp = controlProbe->TemperatureAvg;
  int control
    = Pid[PIDB] + Pid[PIDP] * (error + _pidErrorSum - (Pid[PIDD] * (currentTemp - averageTemp)));

  if (control >= MaxFanSpeed)
    _fanSpeed = MaxFanSpeed;
  else if (control > 0)
    _fanSpeed = control;
}

void GrillPid::commitFanSpeed(void)
{
  calcExpMovingAverage(FANSPEED_AVG_SMOOTH, &FanSpeedAvg, _fanSpeed);

  /* For anything above MINIMUM_FAN_SPEED, do a nomal PWM write.
     For below MINIMUM_FAN_SPEED we use a "long pulse PWM", where
     the pulse is 10 seconds in length.  For each percent we are
     emulating, run the fan for one interval. */
  if (_fanSpeed >= MINIMUM_FAN_SPEED)
  {
    analogWrite(_blowerPin, _fanSpeed * 255 / 100);
    _longPwmTmr = 0;
  }
  else
  {
    // Simple PWM, ON for first [FanSpeed] intervals then OFF
    // for the remainder of the period
    unsigned char pwmVal;
    pwmVal = (_fanSpeed > _longPwmTmr) ? 255/MINIMUM_FAN_SPEED : 0;

    analogWrite(_blowerPin, pwmVal);
    // Long PWM period is 10 intervals
    if (++_longPwmTmr > 9)
      _longPwmTmr = 0;
  }  /* long PWM */
}

boolean GrillPid::isAnyFoodProbeActive(void)
{
  unsigned char i;
  for (i=TEMP_FOOD1; i<TEMP_COUNT; i++)
    if (Probes[i]->Temperature != 0.0f)
      return true;

  return false;
}

void GrillPid::resetLidOpenResumeCountdown(void)
{
  LidOpenResumeCountdown = LidOpenDuration;
  _pitTemperatureReached = false;
}

void GrillPid::setSetPoint(int value)
{
  _setPoint = value;
  _pitTemperatureReached = false;
  _manualFanMode = false;
  _pidErrorSum = 0;
}

void GrillPid::setFanSpeed(int value)
{
  _manualFanMode = true;
  if (value < 0)
    _fanSpeed = 0;
  else if (value > 100)
    _fanSpeed = 100;
  else
    _fanSpeed = value;
}

boolean GrillPid::doWork(void)
{
  unsigned long m = millis();
  if ((m - _lastTempRead) < (1000 / TEMP_AVG_COUNT))
    return false;
  _lastTempRead = m;

  unsigned char i;
  for (i=0; i<TEMP_COUNT; i++)
    Probes[i]->readTemp();

  if (++_accumulatedCount < TEMP_AVG_COUNT)
    return false;

  for (i=0; i<TEMP_COUNT; i++)
    Probes[i]->calcTemp();

  if (!_manualFanMode)
  {
    // Always calculate the fan speed
    // calFanSpeed() will bail if it isn't supposed to be in control
    TempProbe *probePit = Probes[TEMP_PIT];
    calcFanSpeed(probePit);

    int pitTemp = probePit->Temperature;
    if (pitTemp >= _setPoint)
    {
      // When we first achieve temperature, reset any P sum we accumulated during startup
      // If we actually neded that sum to achieve temperature we'll rebuild it, and it
      // prevents bouncing around above the temperature when you first start up
      if (!_pitTemperatureReached)
      {
        _pitTemperatureReached = true;
        _pidErrorSum = 0.0f;
      }
      LidOpenResumeCountdown = 0;
    }
    else if (LidOpenResumeCountdown != 0)
    {
      --LidOpenResumeCountdown;
    }
    // If the pit temperature dropped has more than [lidOpenOffset] degrees
    // after reaching temp, and the fan has not been running more than 90% of
    // the average period. note that the code assumes g_LidOpenResumeCountdown <= 0
    else if (_pitTemperatureReached && ((_setPoint - pitTemp) > (int)LidOpenOffset) && FanSpeedAvg < 90.0f)
    {
      resetLidOpenResumeCountdown();
    }
  }   /* if !manualFanMode */
  commitFanSpeed();

  _accumulatedCount = 0;
  return true;
}

<|endoftext|>