<commit_before>#include "ToolBase.h"
#include "NGSD.h"

class ConcreteTool
		: public ToolBase
{
	Q_OBJECT

public:
	ConcreteTool(int& argc, char *argv[])
		: ToolBase(argc, argv)
	{
	}

	QStringList validPathStrings()
	{
		QStringList output;

		output << "";

		foreach(PathType type, QList<PathType>() << PathType::SAMPLE_FOLDER << PathType::BAM << PathType::VCF << PathType::GSVAR << PathType::COPY_NUMBER_CALLS << PathType::STRUCTURAL_VARIANTS << PathType::MOSAIC_VARIANTS)
		{
			output << FileLocation::typeToString(type);
		}

		return output;
	}

	virtual void setup()
	{
		setDescription("Lists processed samples from the NGSD.");
		addOutfile("out", "Output TSV file. If unset, writes to STDOUT.", true);
		addString("sample", "Sample name filter (substring match).", true, "");
		addFlag("no_bad_samples", "If set, processed samples with 'bad' quality are excluded.");
		addFlag("no_tumor", "If set, tumor samples are excluded.");
		addFlag("no_ffpe", "If set, FFPE samples are excluded.");
		addFlag("match_external_names", "If set, also samples for which the external name matches 'sample' are exported.");
		addFlag("with_merged", "If set, processed samples that were merged into another sample are included.");
		addString("species", "Species filter.", true, "");
		addString("tissue", "Tissue filter.", true, "");
		addString("ancestry", "Ancestry filter.", true, "");
		addString("disease_group", "Disease group filter", true, "");
		addString("disease_status", "Disease status filter", true, "");
		addString("phenotypes", "HPO phenotype identifiers separated by colon, e.g. 'HP:0002066;HP:0004322'", true, "");
		addString("sender", "Sample sender filter.", true, "");
		addString("study", "Processed sample study filter.", true, "");
		addString("project", "Project name filter.", true, "");
		addString("project_type", "Project type filter", true, "");
		addFlag("no_archived_projects", "If set, samples in archived projects are excluded.");
		addString("system", "Processing system name filter (short name).", true, "");
		addString("system_type", "Type of processing system filter", true, "");
		addString("run", "Sequencing run name filter.", true, "");
		addFlag("run_finished", "Only show samples where the analysis of the run is finished.");
		addString("run_device", "Sequencing run device name filter.", true, "");
		addString("run_before", "Sequencing run start date before or equal to the given date.", true, "");
		addFlag("no_bad_runs", "If set, sequencing runs with 'bad' quality are excluded.");
		addFlag("add_qc", "If set, QC columns are added to output.");
		addFlag("add_outcome", "If set, diagnostic outcome columns are added to output.");
		addFlag("add_disease_details", "If set, disease details columns are added to output.");
		addEnum("add_path", "Adds a column with the given path type.", true, validPathStrings());
		addFlag("add_report_config", "Adds a column with report configuration information (exists/has_small_variants/has_cnvs).");
		addFlag("add_comments", "Adds sample and processed sample comments columns.");
		addFlag("add_normal_sample", "Adds a column with the normal germline sample associated to a for tumor samples.");
		addFlag("test", "Uses the test database instead of on the production database.");

		changeLog(2022, 11, 11, "Added 'ancestry' and 'phenotypes' filter options.");
		changeLog(2022,  3,  3, "Added 'disease_group', 'disease_status', 'project_type' and 'tissue' filter options.");
		changeLog(2021,  4, 29, "Added 'run_before' filter option.");
		changeLog(2021,  4, 16, "Added ancestry column.");
		changeLog(2021,  4, 13, "Changed 'add_path' parameter to support different file/folder types.");
		changeLog(2020, 10,  8, "Added parameters 'sender' and 'study'.");
		changeLog(2020,  7, 20, "Added 'match_external_names' flag.");
		changeLog(2019, 12, 11, "Added 'run_finished' and 'add_report_config' flags.");
		changeLog(2019,  5, 17, "Added 'with_merged' flag.");
		changeLog(2019,  4, 12, "Complete refactoring and interface change.");
		changeLog(2019,  1, 10, "Added 'species' filter.");
		changeLog(2018, 10, 23, "Added 'outcome' flag.");
	}

	virtual void main()
	{
		//init
		NGSD db(getFlag("test"));
		QSharedPointer<QFile> output = Helper::openFileForWriting(getOutfile("out"), true);

		ProcessedSampleSearchParameters params;
		params.s_name = getString("sample");
		params.s_name_ext = getFlag("match_external_names");
		params.s_species = getString("species");
		params.s_sender = getString("sender");
		params.s_tissue = getString("tissue");
		params.s_ancestry = getString("ancestry");
		params.s_disease_group = getString("disease_group");
		params.s_disease_status = getString("disease_status");
		foreach(QString hpo_id, getString("phenotypes").split(";"))
		{
			hpo_id = hpo_id.trimmed();
			if (hpo_id.isEmpty()) continue;
			params.s_phenotypes << db.phenotypeChildTerms(db.phenotypeIdByAccession(hpo_id.toUtf8()), true);
		}
		params.s_study = getString("study");
		params.include_bad_quality_samples = !getFlag("no_bad_samples");
		params.include_tumor_samples = !getFlag("no_tumor");
		params.include_ffpe_samples = !getFlag("no_ffpe");
		params.include_merged_samples = getFlag("with_merged");
		params.p_name = getString("project");
		params.p_type = getString("project_type");
		params.include_archived_projects = !getFlag("no_archived_projects");
		params.sys_name = getString("system");
		params.sys_type = getString("system_type");
		params.r_name = getString("run");
		params.include_bad_quality_runs = !getFlag("no_bad_runs");
		params.run_finished = getFlag("run_finished");
		params.r_device_name = getString("run_device");
		if (getString("run_before").trimmed()!="")
		{
			QDate run_start_date = QDate::fromString(getString("run_before"), Qt::ISODate);
			if (!run_start_date.isValid())
			{
				THROW(ArgumentException, "Invalid date given for 'run_before' parameter.\nThe expected format is a ISO date, e.g. '2012-09-27'.");
			}
			params.r_before = run_start_date;
		}
		params.add_qc = getFlag("add_qc");
		params.add_outcome = getFlag("add_outcome");
		params.add_disease_details = getFlag("add_disease_details");
		params.add_path = getEnum("add_path");
		params.add_report_config = getFlag("add_report_config");
		params.add_normal_sample = getFlag("add_normal_sample");
		params.add_comments = getFlag("add_comments");

		//check parameters
		if (params.p_name!="")
		{
			//check that name is valid
			QVariant tmp = db.getValue("SELECT id FROM project WHERE name=:0", true, params.p_name);
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid project name '" + params.p_name + "'.\nValid names are: " + db.getValues("SELECT name FROM project ORDER BY name ASC").join(", "));
			}
		}

		if (params.p_type!="")
		{
			//check that type is valid
			QStringList values = db.getEnum("project", "type");
			if (! values.contains(params.p_type))
			{
				THROW(DatabaseException, "Invalid project type '" + params.p_type + "'.\nValid types are: " + values.join(", "));
			}
		}

		if (params.sys_name!="")
		{
			//check that name is valid
			int sys_id = db.processingSystemId(params.sys_name, false);
			if (sys_id==-1)
			{
				THROW(DatabaseException, "Invalid processing system short name '" + params.sys_name + "'.\nValid names are: " + db.getValues("SELECT name_short FROM processing_system ORDER BY name_short ASC").join(", "));
			}
		}

		if (params.sys_type!="")
		{
			//check that type is valid
			QStringList values = db.getEnum("processing_system", "type");
			if (! values.contains(params.sys_type))
			{
				THROW(DatabaseException, "Invalid processing system type '" + params.sys_type + "'.\nValid types are: " + values.join(", "));
			}
		}

		if (params.r_name!="")
		{
			//check that name is valid
			QVariant tmp = db.getValue("SELECT id FROM sequencing_run WHERE name=:0", true, params.r_name);
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid sequencing run name '"+params.r_name+"'.\nValid names are: " + db.getValues("SELECT name FROM sequencing_run ORDER BY name ASC").join(", "));
			}
		}

		if (params.r_device_name!="")
		{
			//check that name is valid
			QVariant tmp = db.getValue("SELECT id FROM device WHERE name=:0", true, params.r_device_name);
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid sequencing run device name '"+params.r_device_name+"'.\nValid names are: " + db.getValues("SELECT name FROM device ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_species!="")
		{
			//check that name is valid
			QString tmp = db.getValue("SELECT id FROM species WHERE name=:0", true, params.s_species).toString();
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid species name '"+params.s_species+"'.\nValid names are: " + db.getValues("SELECT name FROM species ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_sender!="")
		{
			//check that name is valid
			QString tmp = db.getValue("SELECT id FROM sender WHERE name=:0", true, params.s_sender).toString();
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid sender name '"+params.s_sender+"'.\nValid names are: " + db.getValues("SELECT name FROM sender ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_study!="")
		{
			//check that name is valid
			QString tmp = db.getValue("SELECT id FROM study WHERE name=:0", true, params.s_study).toString();
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid study name '"+params.s_study+"'.\nValid names are: " + db.getValues("SELECT name FROM study ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_tissue !="")
		{
			QStringList values = db.getEnum("sample", "tissue");
			if (! values.contains(params.s_tissue))
			{
				THROW(DatabaseException, "Invalid sample tissue '"+params.s_tissue+"'.\nValid tissues are: " + values.join(", "));
			}
		}

		if (params.s_ancestry !="")
		{
			QStringList values = db.getEnum("processed_sample_ancestry", "population");
			if (! values.contains(params.s_ancestry))
			{
				THROW(DatabaseException, "Invalid sample ancestry '"+params.s_ancestry+"'.\nValid tissues are: " + values.join(", "));
			}
		}

		if (params.s_disease_group !="")
		{
			QStringList values = db.getEnum("sample", "disease_group");
			if (! values.contains(params.s_disease_group))
			{
				THROW(DatabaseException, "Invalid sample disease group '"+params.s_disease_group+"'.\nValid groups are: " + values.join(", "));
			}
		}

		if (params.s_disease_status !="")
		{
			QStringList values = db.getEnum("sample", "disease_status");
			if (! values.contains(params.s_disease_status))
			{
				THROW(DatabaseException, "Invalid sample disease status '"+params.s_disease_status+"'.\nValid statuses are: " + values.join(", "));
			}
		}

		//process
		DBTable table = db.processedSampleSearch(params);
		QTextStream stream(output.data());
		table.write(stream);
	}
};

#include "main.moc"

int main(int argc, char *argv[])
{
	ConcreteTool tool(argc, argv);
	return tool.execute();
}
<commit_msg>NGSDExportSamples: fixed HPO filter<commit_after>#include "ToolBase.h"
#include "NGSD.h"

class ConcreteTool
		: public ToolBase
{
	Q_OBJECT

public:
	ConcreteTool(int& argc, char *argv[])
		: ToolBase(argc, argv)
	{
	}

	QStringList validPathStrings()
	{
		QStringList output;

		output << "";

		foreach(PathType type, QList<PathType>() << PathType::SAMPLE_FOLDER << PathType::BAM << PathType::VCF << PathType::GSVAR << PathType::COPY_NUMBER_CALLS << PathType::STRUCTURAL_VARIANTS << PathType::MOSAIC_VARIANTS)
		{
			output << FileLocation::typeToString(type);
		}

		return output;
	}

	virtual void setup()
	{
		setDescription("Lists processed samples from the NGSD.");
		addOutfile("out", "Output TSV file. If unset, writes to STDOUT.", true);
		addString("sample", "Sample name filter (substring match).", true, "");
		addFlag("no_bad_samples", "If set, processed samples with 'bad' quality are excluded.");
		addFlag("no_tumor", "If set, tumor samples are excluded.");
		addFlag("no_ffpe", "If set, FFPE samples are excluded.");
		addFlag("match_external_names", "If set, also samples for which the external name matches 'sample' are exported.");
		addFlag("with_merged", "If set, processed samples that were merged into another sample are included.");
		addString("species", "Species filter.", true, "");
		addString("tissue", "Tissue filter.", true, "");
		addString("ancestry", "Ancestry filter.", true, "");
		addString("disease_group", "Disease group filter", true, "");
		addString("disease_status", "Disease status filter", true, "");
		addString("phenotypes", "HPO phenotype identifiers separated by colon, e.g. 'HP:0002066;HP:0004322'", true, "");
		addString("sender", "Sample sender filter.", true, "");
		addString("study", "Processed sample study filter.", true, "");
		addString("project", "Project name filter.", true, "");
		addString("project_type", "Project type filter", true, "");
		addFlag("no_archived_projects", "If set, samples in archived projects are excluded.");
		addString("system", "Processing system name filter (short name).", true, "");
		addString("system_type", "Type of processing system filter", true, "");
		addString("run", "Sequencing run name filter.", true, "");
		addFlag("run_finished", "Only show samples where the analysis of the run is finished.");
		addString("run_device", "Sequencing run device name filter.", true, "");
		addString("run_before", "Sequencing run start date before or equal to the given date.", true, "");
		addFlag("no_bad_runs", "If set, sequencing runs with 'bad' quality are excluded.");
		addFlag("add_qc", "If set, QC columns are added to output.");
		addFlag("add_outcome", "If set, diagnostic outcome columns are added to output.");
		addFlag("add_disease_details", "If set, disease details columns are added to output.");
		addEnum("add_path", "Adds a column with the given path type.", true, validPathStrings());
		addFlag("add_report_config", "Adds a column with report configuration information (exists/has_small_variants/has_cnvs).");
		addFlag("add_comments", "Adds sample and processed sample comments columns.");
		addFlag("add_normal_sample", "Adds a column with the normal germline sample associated to a for tumor samples.");
		addFlag("test", "Uses the test database instead of on the production database.");

		changeLog(2022, 11, 11, "Added 'ancestry' and 'phenotypes' filter options.");
		changeLog(2022,  3,  3, "Added 'disease_group', 'disease_status', 'project_type' and 'tissue' filter options.");
		changeLog(2021,  4, 29, "Added 'run_before' filter option.");
		changeLog(2021,  4, 16, "Added ancestry column.");
		changeLog(2021,  4, 13, "Changed 'add_path' parameter to support different file/folder types.");
		changeLog(2020, 10,  8, "Added parameters 'sender' and 'study'.");
		changeLog(2020,  7, 20, "Added 'match_external_names' flag.");
		changeLog(2019, 12, 11, "Added 'run_finished' and 'add_report_config' flags.");
		changeLog(2019,  5, 17, "Added 'with_merged' flag.");
		changeLog(2019,  4, 12, "Complete refactoring and interface change.");
		changeLog(2019,  1, 10, "Added 'species' filter.");
		changeLog(2018, 10, 23, "Added 'outcome' flag.");
	}

	virtual void main()
	{
		//init
		NGSD db(getFlag("test"));
		QSharedPointer<QFile> output = Helper::openFileForWriting(getOutfile("out"), true);

		ProcessedSampleSearchParameters params;
		params.s_name = getString("sample");
		params.s_name_ext = getFlag("match_external_names");
		params.s_species = getString("species");
		params.s_sender = getString("sender");
		params.s_tissue = getString("tissue");
		params.s_ancestry = getString("ancestry");
		params.s_disease_group = getString("disease_group");
		params.s_disease_status = getString("disease_status");
		foreach(QString hpo_id, getString("phenotypes").split(";"))
		{
			hpo_id = hpo_id.trimmed();
			if (hpo_id.isEmpty()) continue;
			params.s_phenotypes << db.phenotype(db.phenotypeIdByAccession(hpo_id.toUtf8()));
		}
		params.s_study = getString("study");
		params.include_bad_quality_samples = !getFlag("no_bad_samples");
		params.include_tumor_samples = !getFlag("no_tumor");
		params.include_ffpe_samples = !getFlag("no_ffpe");
		params.include_merged_samples = getFlag("with_merged");
		params.p_name = getString("project");
		params.p_type = getString("project_type");
		params.include_archived_projects = !getFlag("no_archived_projects");
		params.sys_name = getString("system");
		params.sys_type = getString("system_type");
		params.r_name = getString("run");
		params.include_bad_quality_runs = !getFlag("no_bad_runs");
		params.run_finished = getFlag("run_finished");
		params.r_device_name = getString("run_device");
		if (getString("run_before").trimmed()!="")
		{
			QDate run_start_date = QDate::fromString(getString("run_before"), Qt::ISODate);
			if (!run_start_date.isValid())
			{
				THROW(ArgumentException, "Invalid date given for 'run_before' parameter.\nThe expected format is a ISO date, e.g. '2012-09-27'.");
			}
			params.r_before = run_start_date;
		}
		params.add_qc = getFlag("add_qc");
		params.add_outcome = getFlag("add_outcome");
		params.add_disease_details = getFlag("add_disease_details");
		params.add_path = getEnum("add_path");
		params.add_report_config = getFlag("add_report_config");
		params.add_normal_sample = getFlag("add_normal_sample");
		params.add_comments = getFlag("add_comments");

		//check parameters
		if (params.p_name!="")
		{
			//check that name is valid
			QVariant tmp = db.getValue("SELECT id FROM project WHERE name=:0", true, params.p_name);
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid project name '" + params.p_name + "'.\nValid names are: " + db.getValues("SELECT name FROM project ORDER BY name ASC").join(", "));
			}
		}

		if (params.p_type!="")
		{
			//check that type is valid
			QStringList values = db.getEnum("project", "type");
			if (! values.contains(params.p_type))
			{
				THROW(DatabaseException, "Invalid project type '" + params.p_type + "'.\nValid types are: " + values.join(", "));
			}
		}

		if (params.sys_name!="")
		{
			//check that name is valid
			int sys_id = db.processingSystemId(params.sys_name, false);
			if (sys_id==-1)
			{
				THROW(DatabaseException, "Invalid processing system short name '" + params.sys_name + "'.\nValid names are: " + db.getValues("SELECT name_short FROM processing_system ORDER BY name_short ASC").join(", "));
			}
		}

		if (params.sys_type!="")
		{
			//check that type is valid
			QStringList values = db.getEnum("processing_system", "type");
			if (! values.contains(params.sys_type))
			{
				THROW(DatabaseException, "Invalid processing system type '" + params.sys_type + "'.\nValid types are: " + values.join(", "));
			}
		}

		if (params.r_name!="")
		{
			//check that name is valid
			QVariant tmp = db.getValue("SELECT id FROM sequencing_run WHERE name=:0", true, params.r_name);
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid sequencing run name '"+params.r_name+"'.\nValid names are: " + db.getValues("SELECT name FROM sequencing_run ORDER BY name ASC").join(", "));
			}
		}

		if (params.r_device_name!="")
		{
			//check that name is valid
			QVariant tmp = db.getValue("SELECT id FROM device WHERE name=:0", true, params.r_device_name);
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid sequencing run device name '"+params.r_device_name+"'.\nValid names are: " + db.getValues("SELECT name FROM device ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_species!="")
		{
			//check that name is valid
			QString tmp = db.getValue("SELECT id FROM species WHERE name=:0", true, params.s_species).toString();
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid species name '"+params.s_species+"'.\nValid names are: " + db.getValues("SELECT name FROM species ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_sender!="")
		{
			//check that name is valid
			QString tmp = db.getValue("SELECT id FROM sender WHERE name=:0", true, params.s_sender).toString();
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid sender name '"+params.s_sender+"'.\nValid names are: " + db.getValues("SELECT name FROM sender ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_study!="")
		{
			//check that name is valid
			QString tmp = db.getValue("SELECT id FROM study WHERE name=:0", true, params.s_study).toString();
			if (tmp.isNull())
			{
				THROW(DatabaseException, "Invalid study name '"+params.s_study+"'.\nValid names are: " + db.getValues("SELECT name FROM study ORDER BY name ASC").join(", "));
			}
		}

		if (params.s_tissue !="")
		{
			QStringList values = db.getEnum("sample", "tissue");
			if (! values.contains(params.s_tissue))
			{
				THROW(DatabaseException, "Invalid sample tissue '"+params.s_tissue+"'.\nValid tissues are: " + values.join(", "));
			}
		}

		if (params.s_ancestry !="")
		{
			QStringList values = db.getEnum("processed_sample_ancestry", "population");
			if (! values.contains(params.s_ancestry))
			{
				THROW(DatabaseException, "Invalid sample ancestry '"+params.s_ancestry+"'.\nValid tissues are: " + values.join(", "));
			}
		}

		if (params.s_disease_group !="")
		{
			QStringList values = db.getEnum("sample", "disease_group");
			if (! values.contains(params.s_disease_group))
			{
				THROW(DatabaseException, "Invalid sample disease group '"+params.s_disease_group+"'.\nValid groups are: " + values.join(", "));
			}
		}

		if (params.s_disease_status !="")
		{
			QStringList values = db.getEnum("sample", "disease_status");
			if (! values.contains(params.s_disease_status))
			{
				THROW(DatabaseException, "Invalid sample disease status '"+params.s_disease_status+"'.\nValid statuses are: " + values.join(", "));
			}
		}

		//process
		DBTable table = db.processedSampleSearch(params);
		QTextStream stream(output.data());
		table.write(stream);
	}
};

#include "main.moc"

int main(int argc, char *argv[])
{
	ConcreteTool tool(argc, argv);
	return tool.execute();
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSelectVisiblePoints.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkSelectVisiblePoints.h"

#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkDataSet.h"
#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"

vtkCxxRevisionMacro(vtkSelectVisiblePoints, "1.31");
vtkStandardNewMacro(vtkSelectVisiblePoints);

// Instantiate object with no renderer; window selection turned off;
// tolerance set to 0.01; and select invisible off.
vtkSelectVisiblePoints::vtkSelectVisiblePoints()
{
  this->Renderer = NULL;
  this->SelectionWindow = 0;
  this->Selection[0] = this->Selection[2] = 0;
  this->Selection[1] = this->Selection[3] = 1600;
  this->Tolerance = 0.01;
  this->SelectInvisible = 0;
}

vtkSelectVisiblePoints::~vtkSelectVisiblePoints()
{
  this->SetRenderer(NULL);
}

void vtkSelectVisiblePoints::Execute()
{
  vtkIdType ptId, id;
  int visible;
  vtkPoints *outPts;
  vtkCellArray *outputVertices;
  vtkDataSet *input= this->GetInput();
  vtkPolyData *output=this->GetOutput();
  vtkPointData *inPD=input->GetPointData();
  vtkPointData *outPD=output->GetPointData();
  vtkIdType numPts=input->GetNumberOfPoints();
  double x[4];
  double dx[3], z, diff;
  int selection[4];

  if ( this->Renderer == NULL )
    {
    vtkErrorMacro(<<"Renderer must be set");
    return;
    }

  if ( numPts < 1 )
    {
    return;
    }

  outPts = vtkPoints::New();
  outPts->Allocate(numPts/2+1);
  outPD->CopyAllocate(inPD);

  outputVertices = vtkCellArray::New();
  output->SetVerts(outputVertices);
  outputVertices->Delete();

  int *size = this->Renderer->GetRenderWindow()->GetSize();

  // specify a selection window to avoid querying
  if ( this->SelectionWindow )
    {
      for (int i=0; i<4; i++)
      {
      selection[i] = this->Selection[i];
      }
    }
  else
    {
    selection[0] = selection[2] = 0;
    selection[1] = size[0] - 1;
    selection[3] = size[1] - 1;
    }

  // Grab the composite perspective transform.  This matrix is used to convert
  // each point to view coordinates.  vtkRenderer provides a WorldToView()
  // method but it computes the composite perspective transform each time
  // WorldToView() is called.  This is expensive, so we get the matrix once
  // and handle the transformation ourselves.
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
  double view[4];
  matrix->DeepCopy(this->Renderer->GetActiveCamera()->
                   GetCompositePerspectiveTransformMatrix(1,0,1));

  // If we have more than a few query points, we grab the z-buffer for the
  // selection region all at once and probe the resulting array.  When we
  // have just a few points, we perform individual z-buffer queries.
  const int SimpleQueryLimit = 25;
  float *zPtr = NULL;
  if (numPts > SimpleQueryLimit)
    {
    zPtr = this->Renderer->GetRenderWindow()->
      GetZbufferData(selection[0], selection[2], selection[1], selection[3]);
    }

  int abort=0;
  vtkIdType progressInterval=numPts/20+1;
  x[3] = 1.0;
  for (id=(-1), ptId=0; ptId < numPts && !abort; ptId++)
    {
    // perform conversion
    input->GetPoint(ptId,x);
    matrix->MultiplyPoint(x, view);
    if (view[3] == 0.0)
      {
      continue;
      }
    this->Renderer->SetViewPoint(view[0]/view[3], view[1]/view[3],
                                 view[2]/view[3]);
    this->Renderer->ViewToDisplay();
    this->Renderer->GetDisplayPoint(dx);
    visible = 0;

    if ( ! (ptId % progressInterval) )
      {
      this->UpdateProgress((double)ptId/numPts);
      abort = this->GetAbortExecute();
      }

    // check whether visible and in selection window
    if ( dx[0] >= selection[0] && dx[0] <= selection[1] &&
         dx[1] >= selection[2] && dx[1] <= selection[3] )
      {
      if (numPts > SimpleQueryLimit)
        {
        // Access the value from the captured zbuffer.  Note, we only
        // captured a portion of the zbuffer, so we need to offset dx by
        // the selection window.
        z = zPtr[(int)dx[0] - selection[0]
                 + ((int)dx[1] - selection[2])
                 *(selection[1] - selection[0] + 1)];
        }
      else
        {
        z = this->Renderer->GetZ(static_cast<int>(dx[0]),
                                 static_cast<int>(dx[1]));
        }
      diff = fabs(z-dx[2]);
      if ( diff <= this->Tolerance )
        {
        visible = 1;
        }
      }

    if ( (visible && !this->SelectInvisible) ||
         (!visible && this->SelectInvisible) )
      {
      id = outPts->InsertNextPoint(x);
      output->InsertNextCell(VTK_VERTEX, 1, &id);
      outPD->CopyData(inPD,ptId,id);
      }
    }//for all points

  output->SetPoints(outPts);
  outPts->Delete();
  output->Squeeze();

  matrix->Delete();

  if (zPtr)
    {
    delete [] zPtr;
    }

  vtkDebugMacro(<<"Selected " << id + 1 << " out of "
                << numPts << " original points");
}

unsigned long int vtkSelectVisiblePoints::GetMTime()
{
  unsigned long mTime=this->vtkDataSetToPolyDataFilter::GetMTime();
  unsigned long time;

  if ( this->Renderer != NULL )
    {
    time = this->Renderer->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

void vtkSelectVisiblePoints::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Renderer: " << this->Renderer << "\n";
  os << indent << "Selection Window: "
     << (this->SelectionWindow ? "On\n" : "Off\n");

  os << indent << "Selection: \n";
  os << indent << "  Xmin,Xmax: (" << this->Selection[0] << ", "
     << this->Selection[1] << ")\n";
  os << indent << "  Ymin,Ymax: (" << this->Selection[2] << ", "
     << this->Selection[3] << ")\n";

  os << indent << "Tolerance: " << this->Tolerance << "\n";
  os << indent << "Select Invisible: "
     << (this->SelectInvisible ? "On\n" : "Off\n");
}
<commit_msg>FIX: Bug #174 - vtkSelectVisiblePoints not getting some valid points as visible. Thanks to Clinton Stimpson for sending demo and patch.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSelectVisiblePoints.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkSelectVisiblePoints.h"

#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkDataSet.h"
#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"

vtkCxxRevisionMacro(vtkSelectVisiblePoints, "1.32");
vtkStandardNewMacro(vtkSelectVisiblePoints);

// Instantiate object with no renderer; window selection turned off;
// tolerance set to 0.01; and select invisible off.
vtkSelectVisiblePoints::vtkSelectVisiblePoints()
{
  this->Renderer = NULL;
  this->SelectionWindow = 0;
  this->Selection[0] = this->Selection[2] = 0;
  this->Selection[1] = this->Selection[3] = 1600;
  this->Tolerance = 0.01;
  this->SelectInvisible = 0;
}

vtkSelectVisiblePoints::~vtkSelectVisiblePoints()
{
  this->SetRenderer(NULL);
}

void vtkSelectVisiblePoints::Execute()
{
  vtkIdType ptId, id;
  int visible;
  vtkPoints *outPts;
  vtkCellArray *outputVertices;
  vtkDataSet *input= this->GetInput();
  vtkPolyData *output=this->GetOutput();
  vtkPointData *inPD=input->GetPointData();
  vtkPointData *outPD=output->GetPointData();
  vtkIdType numPts=input->GetNumberOfPoints();
  double x[4];
  double dx[3], z;
  int selection[4];

  if ( this->Renderer == NULL )
    {
    vtkErrorMacro(<<"Renderer must be set");
    return;
    }

  if ( numPts < 1 )
    {
    return;
    }

  outPts = vtkPoints::New();
  outPts->Allocate(numPts/2+1);
  outPD->CopyAllocate(inPD);

  outputVertices = vtkCellArray::New();
  output->SetVerts(outputVertices);
  outputVertices->Delete();

  int *size = this->Renderer->GetRenderWindow()->GetSize();

  // specify a selection window to avoid querying
  if ( this->SelectionWindow )
    {
      for (int i=0; i<4; i++)
      {
      selection[i] = this->Selection[i];
      }
    }
  else
    {
    selection[0] = selection[2] = 0;
    selection[1] = size[0] - 1;
    selection[3] = size[1] - 1;
    }

  // Grab the composite perspective transform.  This matrix is used to convert
  // each point to view coordinates.  vtkRenderer provides a WorldToView()
  // method but it computes the composite perspective transform each time
  // WorldToView() is called.  This is expensive, so we get the matrix once
  // and handle the transformation ourselves.
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
  double view[4];
  matrix->DeepCopy(this->Renderer->GetActiveCamera()->
                   GetCompositePerspectiveTransformMatrix(1,0,1));

  // If we have more than a few query points, we grab the z-buffer for the
  // selection region all at once and probe the resulting array.  When we
  // have just a few points, we perform individual z-buffer queries.
  const int SimpleQueryLimit = 25;
  float *zPtr = NULL;
  if (numPts > SimpleQueryLimit)
    {
    zPtr = this->Renderer->GetRenderWindow()->
      GetZbufferData(selection[0], selection[2], selection[1], selection[3]);
    }

  int abort=0;
  vtkIdType progressInterval=numPts/20+1;
  x[3] = 1.0;
  for (id=(-1), ptId=0; ptId < numPts && !abort; ptId++)
    {
    // perform conversion
    input->GetPoint(ptId,x);
    matrix->MultiplyPoint(x, view);
    if (view[3] == 0.0)
      {
      continue;
      }
    this->Renderer->SetViewPoint(view[0]/view[3], view[1]/view[3],
                                 view[2]/view[3]);
    this->Renderer->ViewToDisplay();
    this->Renderer->GetDisplayPoint(dx);
    visible = 0;

    if ( ! (ptId % progressInterval) )
      {
      this->UpdateProgress((double)ptId/numPts);
      abort = this->GetAbortExecute();
      }

    // check whether visible and in selection window
    if ( dx[0] >= selection[0] && dx[0] <= selection[1] &&
         dx[1] >= selection[2] && dx[1] <= selection[3] )
      {
      if (numPts > SimpleQueryLimit)
        {
        // Access the value from the captured zbuffer.  Note, we only
        // captured a portion of the zbuffer, so we need to offset dx by
        // the selection window.
        z = zPtr[(int)dx[0] - selection[0]
                 + ((int)dx[1] - selection[2])
                 *(selection[1] - selection[0] + 1)];
        }
      else
        {
        z = this->Renderer->GetZ(static_cast<int>(dx[0]),
                                 static_cast<int>(dx[1]));
        }
      if( dx[2] < (z + this->Tolerance) )
        {
        visible = 1;
        }
      }

    if ( (visible && !this->SelectInvisible) ||
         (!visible && this->SelectInvisible) )
      {
      id = outPts->InsertNextPoint(x);
      output->InsertNextCell(VTK_VERTEX, 1, &id);
      outPD->CopyData(inPD,ptId,id);
      }
    }//for all points

  output->SetPoints(outPts);
  outPts->Delete();
  output->Squeeze();

  matrix->Delete();

  if (zPtr)
    {
    delete [] zPtr;
    }

  vtkDebugMacro(<<"Selected " << id + 1 << " out of "
                << numPts << " original points");
}

unsigned long int vtkSelectVisiblePoints::GetMTime()
{
  unsigned long mTime=this->vtkDataSetToPolyDataFilter::GetMTime();
  unsigned long time;

  if ( this->Renderer != NULL )
    {
    time = this->Renderer->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

void vtkSelectVisiblePoints::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Renderer: " << this->Renderer << "\n";
  os << indent << "Selection Window: "
     << (this->SelectionWindow ? "On\n" : "Off\n");

  os << indent << "Selection: \n";
  os << indent << "  Xmin,Xmax: (" << this->Selection[0] << ", "
     << this->Selection[1] << ")\n";
  os << indent << "  Ymin,Ymax: (" << this->Selection[2] << ", "
     << this->Selection[3] << ")\n";

  os << indent << "Tolerance: " << this->Tolerance << "\n";
  os << indent << "Select Invisible: "
     << (this->SelectInvisible ? "On\n" : "Off\n");
}
<|endoftext|>


<commit_before>
#include <Onsang/utility.hpp>
#include <Onsang/Log.hpp>
#include <Onsang/asio.hpp>
#include <Onsang/serialization.hpp>
#include <Onsang/Net/CmdStreamer.hpp>

#include <Hord/Error.hpp>
#include <Hord/ErrorCode.hpp>

#include <duct/IO/arithmetic.hpp>

#include <cassert>
#include <limits>
#include <mutex>
#include <iomanip>
#include <iostream>

#include <Onsang/detail/gr_ceformat.hpp>

namespace Onsang {
namespace Net {

// class CmdStreamer implementation

#define ONSANG_SCOPE_CLASS Net::CmdStreamer

namespace {

enum : unsigned {
	// uint32 size
	// uint32 type
	msg_header_size = 8u,

	// stage : 8
	// cmd   : 24
	mask_type_stage	= 0x000000FF,
	mask_type_cmd	= 0xFFFFFF00
};

static constexpr ceformat::Format const
	s_err_command_type_invalid{
		": command type %#08x is invalid\n"
	},
	s_err_stage_type_invalid{
		": stage type %#02x is invalid for command type %#08x\n"
	}
;

} // anonymous namespace

#define ONSANG_SCOPE_FUNC read_header
bool
CmdStreamer::read_header() {
	std::istream stream{&m_streambuf_in};
	std::size_t const size
	= duct::IO::read_arithmetic<std::uint32_t>(
		stream,
		duct::Endian::little
	);

	std::uint32_t const type
	= duct::IO::read_arithmetic<std::uint32_t>(
		stream,
		duct::Endian::little
	);

	if (stream.fail()) {
		return false;
	} else {
		m_incoming_size = size;
		m_incoming_type = type;
		return true;
	}
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC read_stage
bool
CmdStreamer::read_stage() {
	auto const command_type = static_cast<Hord::Cmd::Type>(
		m_incoming_type & mask_type_cmd
	);
	auto const stage_type = static_cast<Hord::Cmd::StageType>(
		m_incoming_type & mask_type_stage
	);

	Hord::Cmd::StageUPtr stage_uptr;
	Hord::Cmd::type_info const* const
	type_info = m_driver.get_command_type_info(
		command_type
	);
	if (!type_info) {
		Log::acquire(Log::error)
			<< ONSANG_SCOPE_FQN_STR_LIT
			<< ceformat::write_sentinel<
				s_err_command_type_invalid
			>(
				enum_cast(command_type)
			)
		;
		return false;
	}

	try {
		stage_uptr.reset(type_info->construct_stage(stage_type));
		std::istream stream{&m_streambuf_in};
		auto ser = make_input_serializer(stream);
		ser(*stage_uptr);
	} catch (Hord::Error& ex) {
		stage_uptr.reset();
		switch (ex.get_code()) {
		case Hord::ErrorCode::cmd_construct_stage_type_invalid:
			Log::acquire(Log::error)
				<< ONSANG_SCOPE_FQN_STR_LIT
				<< ceformat::write_sentinel<s_err_stage_type_invalid>(
					enum_cast(stage_type),
					enum_cast(command_type)
				)
			;
			return false;

		// IO error or malformed data
		default:
			return false;
		}
	} catch (...) {
		throw;
	}

	std::size_t const remaining = m_streambuf_in.get_remaining();
	if (0u < remaining) {
		Log::acquire(Log::debug)
			<< ONSANG_SCOPE_FQN_STR_LIT
			<< ": "
			<< remaining
			<< " bytes left in buffer after stage deserialization\n"
		;
	}

	{
		std::lock_guard<std::mutex> m_lock{m_stage_buffer_mutex};
		m_stage_buffer.emplace_back(std::move(stage_uptr));
		m_sig_have_stages.store(true);
	}

	return true;
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC chain_read_header
void
CmdStreamer::chain_read_header() {
	m_incoming_size = 0u;
	assert(m_streambuf_in.reset(msg_header_size));
	asio::async_read(
		m_socket,
		asio::buffer(
			m_streambuf_in.get_buffer().data(),
			msg_header_size
		),
		asio::transfer_exactly(msg_header_size),
		[this](
			boost::system::error_code const ec,
			std::size_t /*length*/
		) {
			if (!ec) {
				m_streambuf_in.commit_direct(msg_header_size, false);
				read_header();
				chain_read_stage();
			} else {
				halt();
			}
		}
	);
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC chain_read_stage
void
CmdStreamer::chain_read_stage() {
	assert(0u <  m_incoming_size);
	assert(0u != m_incoming_type);

	assert(m_streambuf_in.reset(m_incoming_size));
	asio::async_read(
		m_socket,
		asio::buffer(
			m_streambuf_in.get_buffer().data(),
			m_incoming_size
		),
		asio::transfer_exactly(m_incoming_size),
		[this](
			boost::system::error_code const ec,
			std::size_t /*length*/
		) {
			if (!ec) {
				m_streambuf_in.commit_direct(m_incoming_size, true);
				read_stage();
				chain_read_header();
			} else {
				halt();
			}
		}
	);
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC chain_flush_output
void
CmdStreamer::chain_flush_output() {
	assert(0u < m_outgoing_size);

	asio::async_write(
		m_socket,
		asio::buffer(
			make_const(m_streambuf_out).get_buffer().data(),
			m_outgoing_size
		),
		asio::transfer_exactly(m_incoming_size),
		[this](
			boost::system::error_code const ec,
			std::size_t /*length*/
		) {
			m_sig_pending_output.store(false);
			m_outgoing_size = 0u;
			if (ec) {
				halt();
			}
		}
	);
}
#undef ONSANG_SCOPE_FUNC

// operations

void
CmdStreamer::halt() noexcept {
	m_socket.get_io_service().stop();
}

#define ONSANG_SCOPE_FUNC run
void
CmdStreamer::run() {
	auto& io_service = m_socket.get_io_service();
	try {
		while (!io_service.stopped()) {
			chain_read_header();
			io_service.run();
		}
	} catch (std::exception& ex) {
		Log::acquire(Log::error)
			<< ONSANG_SCOPE_FQN_STR_LIT
			<< ": caught exception from io_service::run(): "
			<< ex.what()
			<< "\n"
		;
		throw;
	}
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC context_input
bool
CmdStreamer::context_input(
	Hord::System::Context& context
) {
	if (!m_sig_have_stages.load()) {
		return false;
	}

	{
		std::lock_guard<std::mutex> m_lock{m_stage_buffer_mutex};
		for (auto& stage_uptr : m_stage_buffer) {
			context.push_input(stage_uptr);
		}
		m_stage_buffer.clear();
		m_sig_have_stages.store(false);
	}

	return true;
}
#undef ONSANG_SCOPE_FUNC

// TODO: What should the exception specifications for this be?
// Does it leave it up to the callee? Seems to be the intention.
#define ONSANG_SCOPE_FUNC context_output
bool
CmdStreamer::context_output(
	Hord::System::Context& context
) {
	if (
		0 == context.get_output().size() ||
		m_sig_pending_output.load()
	) {
		return false;
	}

	m_streambuf_out.reset(
		msg_header_size + (m_streambuf_out.get_max_size() >> 2)
	);
	std::ostream stream{&m_streambuf_out};
	auto ser = make_output_serializer(stream);

	// Seek past header to reserve it; we need the size of the
	// stage payload
	stream.seekp(msg_header_size);

	// data
	auto& stage = *context.get_output().front();
	ser(stage);

	// Can't use buffer.size() later because it might've grown
	// beyond our write amount
	m_outgoing_size = m_streambuf_out.get_sequence_size();

	// header
	stream.seekp(0);
	std::size_t const h_size = m_outgoing_size - msg_header_size;
	assert(std::numeric_limits<std::uint32_t>::max() >= h_size);
	ser(static_cast<std::uint32_t>(h_size));

	std::uint32_t const h_type
		= enum_cast(stage.get_stage_type())
		| enum_cast(stage.get_command_type())
	;
	ser(h_type);

	if (stream.fail()) {
		return false;
	}
	m_streambuf_out.commit();

	context.get_output().pop_front();
	m_sig_pending_output.store(true);

	m_socket.get_io_service().post(
		[this]() {
			chain_flush_output();
		}
	);

	return true;
}
#undef ONSANG_SCOPE_FUNC

#undef ONSANG_SCOPE_CLASS // Onsang::Net::CmdStreamer

} // namespace Net
} // namespace Onsang
<commit_msg>Net::CmdStreamer: updated use of Context and Cmd::type_info.<commit_after>
#include <Onsang/utility.hpp>
#include <Onsang/Log.hpp>
#include <Onsang/asio.hpp>
#include <Onsang/serialization.hpp>
#include <Onsang/Net/CmdStreamer.hpp>

#include <Hord/Error.hpp>
#include <Hord/ErrorCode.hpp>

#include <duct/IO/arithmetic.hpp>

#include <cassert>
#include <limits>
#include <mutex>
#include <iomanip>
#include <iostream>

#include <Onsang/detail/gr_ceformat.hpp>

namespace Onsang {
namespace Net {

// class CmdStreamer implementation

#define ONSANG_SCOPE_CLASS Net::CmdStreamer

namespace {

enum : unsigned {
	// uint32 size
	// uint32 type
	msg_header_size = 8u,

	// stage : 8
	// cmd   : 24
	mask_type_stage	= 0x000000FF,
	mask_type_cmd	= 0xFFFFFF00
};

static constexpr ceformat::Format const
	s_err_command_type_invalid{
		": command type %#08x is invalid\n"
	},
	s_err_stage_type_invalid{
		": stage type %#02x is invalid for command type %#08x\n"
	}
;

} // anonymous namespace

#define ONSANG_SCOPE_FUNC read_header
bool
CmdStreamer::read_header() {
	std::istream stream{&m_streambuf_in};
	std::size_t const size
	= duct::IO::read_arithmetic<std::uint32_t>(
		stream,
		duct::Endian::little
	);

	std::uint32_t const type
	= duct::IO::read_arithmetic<std::uint32_t>(
		stream,
		duct::Endian::little
	);

	if (stream.fail()) {
		return false;
	} else {
		m_incoming_size = size;
		m_incoming_type = type;
		return true;
	}
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC read_stage
bool
CmdStreamer::read_stage() {
	auto const command_type = static_cast<Hord::Cmd::Type>(
		m_incoming_type & mask_type_cmd
	);
	auto const stage_type = static_cast<Hord::Cmd::StageType>(
		m_incoming_type & mask_type_stage
	);

	Hord::Cmd::StageUPtr stage_uptr;
	Hord::Cmd::type_info const* const
	type_info = m_driver.get_command_type_info(
		command_type
	);
	if (!type_info) {
		Log::acquire(Log::error)
			<< ONSANG_SCOPE_FQN_STR_LIT
			<< ceformat::write_sentinel<
				s_err_command_type_invalid
			>(
				enum_cast(command_type)
			)
		;
		return false;
	}

	try {
		stage_uptr = type_info->make_stage(stage_type);
		std::istream stream{&m_streambuf_in};
		auto ser = make_input_serializer(stream);
		ser(*stage_uptr);
	} catch (Hord::Error& ex) {
		stage_uptr.reset();
		switch (ex.get_code()) {
		case Hord::ErrorCode::cmd_construct_stage_type_invalid:
			Log::acquire(Log::error)
				<< ONSANG_SCOPE_FQN_STR_LIT
				<< ceformat::write_sentinel<s_err_stage_type_invalid>(
					enum_cast(stage_type),
					enum_cast(command_type)
				)
			;
			return false;

		// IO error or malformed data
		default:
			return false;
		}
	} catch (...) {
		throw;
	}

	std::size_t const remaining = m_streambuf_in.get_remaining();
	if (0u < remaining) {
		Log::acquire(Log::debug)
			<< ONSANG_SCOPE_FQN_STR_LIT
			<< ": "
			<< remaining
			<< " bytes left in buffer after stage deserialization\n"
		;
	}

	{
		std::lock_guard<std::mutex> m_lock{m_stage_buffer_mutex};
		m_stage_buffer.emplace_back(std::move(stage_uptr));
		m_sig_have_stages.store(true);
	}

	return true;
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC chain_read_header
void
CmdStreamer::chain_read_header() {
	m_incoming_size = 0u;
	assert(m_streambuf_in.reset(msg_header_size));
	asio::async_read(
		m_socket,
		asio::buffer(
			m_streambuf_in.get_buffer().data(),
			msg_header_size
		),
		asio::transfer_exactly(msg_header_size),
		[this](
			boost::system::error_code const ec,
			std::size_t /*length*/
		) {
			if (!ec) {
				m_streambuf_in.commit_direct(msg_header_size, false);
				read_header();
				chain_read_stage();
			} else {
				halt();
			}
		}
	);
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC chain_read_stage
void
CmdStreamer::chain_read_stage() {
	assert(0u <  m_incoming_size);
	assert(0u != m_incoming_type);

	assert(m_streambuf_in.reset(m_incoming_size));
	asio::async_read(
		m_socket,
		asio::buffer(
			m_streambuf_in.get_buffer().data(),
			m_incoming_size
		),
		asio::transfer_exactly(m_incoming_size),
		[this](
			boost::system::error_code const ec,
			std::size_t /*length*/
		) {
			if (!ec) {
				m_streambuf_in.commit_direct(m_incoming_size, true);
				read_stage();
				chain_read_header();
			} else {
				halt();
			}
		}
	);
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC chain_flush_output
void
CmdStreamer::chain_flush_output() {
	assert(0u < m_outgoing_size);

	asio::async_write(
		m_socket,
		asio::buffer(
			make_const(m_streambuf_out).get_buffer().data(),
			m_outgoing_size
		),
		asio::transfer_exactly(m_incoming_size),
		[this](
			boost::system::error_code const ec,
			std::size_t /*length*/
		) {
			m_sig_pending_output.store(false);
			m_outgoing_size = 0u;
			if (ec) {
				halt();
			}
		}
	);
}
#undef ONSANG_SCOPE_FUNC

// operations

void
CmdStreamer::halt() noexcept {
	m_socket.get_io_service().stop();
}

#define ONSANG_SCOPE_FUNC run
void
CmdStreamer::run() {
	auto& io_service = m_socket.get_io_service();
	try {
		while (!io_service.stopped()) {
			chain_read_header();
			io_service.run();
		}
	} catch (std::exception& ex) {
		Log::acquire(Log::error)
			<< ONSANG_SCOPE_FQN_STR_LIT
			<< ": caught exception from io_service::run(): "
			<< ex.what()
			<< "\n"
		;
		throw;
	}
}
#undef ONSANG_SCOPE_FUNC

#define ONSANG_SCOPE_FUNC context_input
bool
CmdStreamer::context_input(
	Hord::System::Context& context
) {
	if (!m_sig_have_stages.load()) {
		return false;
	}

	{
		std::lock_guard<std::mutex> m_lock{m_stage_buffer_mutex};
		for (auto& stage_uptr : m_stage_buffer) {
			context.push_input(std::move(stage_uptr));
		}
		m_stage_buffer.clear();
		m_sig_have_stages.store(false);
	}

	return true;
}
#undef ONSANG_SCOPE_FUNC

// TODO: What should the exception specifications for this be?
// Does it leave it up to the callee? Seems to be the intention.
#define ONSANG_SCOPE_FUNC context_output
bool
CmdStreamer::context_output(
	Hord::System::Context& context
) {
	if (
		0 == context.get_output().size() ||
		m_sig_pending_output.load()
	) {
		return false;
	}

	m_streambuf_out.reset(
		msg_header_size + (m_streambuf_out.get_max_size() >> 2)
	);
	std::ostream stream{&m_streambuf_out};
	auto ser = make_output_serializer(stream);

	// Seek past header to reserve it; we need the size of the
	// stage payload
	stream.seekp(msg_header_size);

	// data
	auto& stage = *context.get_output().front().stage;
	ser(stage);

	// Can't use buffer.size() later because it might've grown
	// beyond our write amount
	m_outgoing_size = m_streambuf_out.get_sequence_size();

	// header
	stream.seekp(0);
	std::size_t const h_size = m_outgoing_size - msg_header_size;
	assert(std::numeric_limits<std::uint32_t>::max() >= h_size);
	ser(static_cast<std::uint32_t>(h_size));

	std::uint32_t const h_type
		= enum_cast(stage.get_stage_type())
		| enum_cast(stage.get_command_type())
	;
	ser(h_type);

	if (stream.fail()) {
		return false;
	}
	m_streambuf_out.commit();

	context.get_output().pop_front();
	m_sig_pending_output.store(true);

	m_socket.get_io_service().post(
		[this]() {
			chain_flush_output();
		}
	);

	return true;
}
#undef ONSANG_SCOPE_FUNC

#undef ONSANG_SCOPE_CLASS // Onsang::Net::CmdStreamer

} // namespace Net
} // namespace Onsang
<|endoftext|>


<commit_before>#include "TestState.h"
#include "DDSLoader.h"
#include "File.h"
#include "OpenGL.h"
#include "StateMachine.h"

#include <cstring>

struct TestState::PrivateData
{
	GLuint shaderProgram;

	GLuint fontTexture;
	size_t fontTextureWidth;
	size_t fontTextureHeight;
	size_t fontTextureDepth;
	GLenum fontTextureBindTarget;

	GLuint vertexArray;
	GLuint vertexBuffer[2];
};

TestState::TestState() : m(new PrivateData)
{
	File vsFile("assets/shaders/text.vs");
	GLuint vs = createShader(GL_VERTEX_SHADER, vsFile.getData(), vsFile.getSize());

	File fsFile("assets/shaders/text.fs");
	GLuint fs = createShader(GL_FRAGMENT_SHADER, fsFile.getData(), fsFile.getSize());

	m->shaderProgram = createProgram(vs, fs);
	glUseProgram(m->shaderProgram);
	glUniform1i(glGetUniformLocation(m->shaderProgram, "u_sampler"), 0);

	File fontTextureFile("assets/fonts/eurostile_extended_18px_0.dds");
	m->fontTexture = loadDDS(fontTextureFile.getData(), fontTextureFile.getSize(), true, m->fontTextureWidth, m->fontTextureHeight, m->fontTextureDepth, m->fontTextureBindTarget);

	glGenVertexArrays(1, &m->vertexArray);
	glBindVertexArray(m->vertexArray);

	const float w = 0.5f;
	const float h = 0.5f;
	float vertices[] = { -w, -h, w, -h, w, h, w, h, -w, h, -w, -h };
	float uvs[] = { 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 0.f, 1.f, 0.f, 0.f };

	glGenBuffers(2, m->vertexBuffer);

	glBindBuffer(GL_ARRAY_BUFFER, m->vertexBuffer[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, m->vertexBuffer[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);
}

TestState::~TestState()
{
	delete m;
}

void TestState::enter(StateMachine* stateMachine)
{
}

void TestState::leave(StateMachine* stateMachine)
{
}

void TestState::update(StateMachine* stateMachine)
{
}

void TestState::render(StateMachine* stateMachine)
{
	glViewport(0, 0, stateMachine->getFramebufferWidth(), stateMachine->getFramebufferHeight());
	glClearColor(0.f, 0.f, 1.f, 1.f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glUseProgram(m->shaderProgram);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(m->fontTextureBindTarget, m->fontTexture);

	glBindVertexArray(m->vertexArray);

	glDrawArrays(GL_TRIANGLES, 0, 6);
}

void TestState::mouseDown(StateMachine* stateMachine, float x, float y)
{
	stateMachine->requestState("menu");
}

void TestState::mouseUp(StateMachine* stateMachine, float x, float y)
{
}

void TestState::mouseMove(StateMachine* stateMachine, float x, float y)
{
}
<commit_msg>Removed an unnecessary include.<commit_after>#include "TestState.h"
#include "DDSLoader.h"
#include "File.h"
#include "OpenGL.h"
#include "StateMachine.h"

struct TestState::PrivateData
{
	GLuint shaderProgram;

	GLuint fontTexture;
	size_t fontTextureWidth;
	size_t fontTextureHeight;
	size_t fontTextureDepth;
	GLenum fontTextureBindTarget;

	GLuint vertexArray;
	GLuint vertexBuffer[2];
};

TestState::TestState() : m(new PrivateData)
{
	File vsFile("assets/shaders/text.vs");
	GLuint vs = createShader(GL_VERTEX_SHADER, vsFile.getData(), vsFile.getSize());

	File fsFile("assets/shaders/text.fs");
	GLuint fs = createShader(GL_FRAGMENT_SHADER, fsFile.getData(), fsFile.getSize());

	m->shaderProgram = createProgram(vs, fs);
	glUseProgram(m->shaderProgram);
	glUniform1i(glGetUniformLocation(m->shaderProgram, "u_sampler"), 0);

	File fontTextureFile("assets/fonts/eurostile_extended_18px_0.dds");
	m->fontTexture = loadDDS(fontTextureFile.getData(), fontTextureFile.getSize(), true, m->fontTextureWidth, m->fontTextureHeight, m->fontTextureDepth, m->fontTextureBindTarget);

	glGenVertexArrays(1, &m->vertexArray);
	glBindVertexArray(m->vertexArray);

	const float w = 0.5f;
	const float h = 0.5f;
	float vertices[] = { -w, -h, w, -h, w, h, w, h, -w, h, -w, -h };
	float uvs[] = { 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 0.f, 1.f, 0.f, 0.f };

	glGenBuffers(2, m->vertexBuffer);

	glBindBuffer(GL_ARRAY_BUFFER, m->vertexBuffer[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, m->vertexBuffer[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);
}

TestState::~TestState()
{
	delete m;
}

void TestState::enter(StateMachine* stateMachine)
{
}

void TestState::leave(StateMachine* stateMachine)
{
}

void TestState::update(StateMachine* stateMachine)
{
}

void TestState::render(StateMachine* stateMachine)
{
	glViewport(0, 0, stateMachine->getFramebufferWidth(), stateMachine->getFramebufferHeight());
	glClearColor(0.f, 0.f, 1.f, 1.f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glUseProgram(m->shaderProgram);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(m->fontTextureBindTarget, m->fontTexture);

	glBindVertexArray(m->vertexArray);

	glDrawArrays(GL_TRIANGLES, 0, 6);
}

void TestState::mouseDown(StateMachine* stateMachine, float x, float y)
{
	stateMachine->requestState("menu");
}

void TestState::mouseUp(StateMachine* stateMachine, float x, float y)
{
}

void TestState::mouseMove(StateMachine* stateMachine, float x, float y)
{
}
<|endoftext|>


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

namespace nocontrol {

// -------------------------------------------------------------------------- //
// Openflow handler

// A scope guard that guarantees messages are always written before
// returning from the function.
struct Ofp_handler::Write_on_exit {
  Write_on_exit(Ofp_handler& c) : conn(c) { }
  ~Write_on_exit() { conn.write(); }
  Ofp_handler& conn;
};

inline
Ofp_handler::Ofp_handler(ff::Reactor& r, ff::Socket&& s, ff::Controller& c)
  : ff::Socket_handler(r, ff::READ_EVENTS | ff::TIME_EVENTS, std::move(s))
  , ctrl_(c)
{ }

/// Create a version negotiation state machine so we know what version
/// we should accept.
///
/// \todo Error checking.
inline bool
Ofp_handler::on_open() {
  // Write_on_exit g(*this);
  // proto_ = new ff::ofp::Protocol(&ctrl_, this);
  // return proto_->on_open(reactor());
  std::cout << "* open OFP\n";
  return true;
}

/// Shutdown the state machine and delete the handler.
inline bool
Ofp_handler::on_close() {
  // Write_on_exit g(*this);
  // proto_->on_close(reactor());
  // delete this;
  std::cout << "* close OFP\n";
  return true;
}

/// When data is available, read as many messages as possibly and send
/// them to the state machine.
///
/// \todo Error checking.
inline bool
Ofp_handler::on_read() {
  // Write_on_exit g(*this);
  // if (not read())
  //   return false;
  // return proto_->on_recv(reactor());

  char buf[2048];
  ff::System_result res = rc().read(buf, 2048);
  if (res and res.value() == 0)
    return false;
  return true;
}

/// When a timeout occurs, notify the protocol of the expired timer.
inline bool
Ofp_handler::on_time(int t) {
  // Write_on_exit g(*this);
  // return proto_->on_time(reactor(), t);
  return true;
}

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

namespace nocontrol {

// -------------------------------------------------------------------------- //
// Openflow handler

// A scope guard that guarantees messages are always written before
// returning from the function.
struct Ofp_handler::Write_on_exit {
  Write_on_exit(Ofp_handler& c) : conn(c) { }
  ~Write_on_exit() { conn.write(); }
  Ofp_handler& conn;
};

inline
Ofp_handler::Ofp_handler(ff::Reactor& r, ff::Socket&& s, ff::Controller& c)
  : ff::Socket_handler(r, ff::READ_EVENTS | ff::TIME_EVENTS, std::move(s))
  , ctrl_(c)
{ }

/// Create a version negotiation state machine so we know what version
/// we should accept.
///
/// \todo Error checking.
inline bool
Ofp_handler::on_open() {
  // Write_on_exit g(*this);
  // proto_ = new ff::ofp::Protocol(&ctrl_, this);
  // return proto_->on_open(reactor());
  std::cout << "* Open OFP connection\n";
  return true;
}

/// Shutdown the state machine and delete the handler.
inline bool
Ofp_handler::on_close() {
  // Write_on_exit g(*this);
  // proto_->on_close(reactor());
  // delete this;
  std::cout << "* close OFP connection\n";
  return true;
}

/// When data is available, read as many messages as possibly and send
/// them to the state machine.
///
/// \todo Error checking.
inline bool
Ofp_handler::on_read() {
  // Write_on_exit g(*this);
  // if (not read())
  //   return false;
  // return proto_->on_recv(reactor());

  char buf[2048];
  ff::System_result res = rc().read(buf, 2048);
  if (res and res.value() == 0)
    return false;
  return true;
}

/// When a timeout occurs, notify the protocol of the expired timer.
inline bool
Ofp_handler::on_time(int t) {
  // Write_on_exit g(*this);
  // return proto_->on_time(reactor(), t);
  return true;
}

} // namespace nocontrol
<|endoftext|>


<commit_before>#ifndef __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
#define __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__

#ifndef DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&);               \
  void operator=(const TypeName&)
#endif

#ifdef _DEBUG
#include "odbgstream.hpp"
#include "hrtext.hpp"
#include "iidstr.hpp"

// Simple trace logging macro that expands to nothing in release mode builds.
// Output is sent to the vs console.
#define DBGLOG(X) \
do { \
    wodbgstream wos; \
    wos << "["__FUNCTION__"] " << X << std::endl; \
} while(0)

// Extract error from the HRESULT, and output its hex and decimal values.
#define \
    HRLOG(X) L" {" << #X << L"=" << X << L"/" << std::hex << X << std::dec \
    << L" (" << hrtext(X) << L")}"

// Convert 100ns units to seconds
#define REFTIMETOSECONDS(X) (double(X) / 10000000.0f)

#else
#define DBGLOG(X)
#define REFTIMETOSECONDS(X)
#endif

// Keep the compiler quiet about do/while(0)'s (constant conditional) used in
// log macros.
#pragma warning(disable:4127)

// Check the HRESULT for failure (<0), and log it if we're in debug mode, and
// format the failure text so that it is clickable in vs output window.
#define CHK(X, Y) \
do { \
    if (FAILED(X=(Y))) \
    { \
        DBGLOG(__FILE__ << "(" << __LINE__ << ") : " << #Y << HRLOG(X)); \
    } \
} while (0)

#endif // __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
<commit_msg>debugutil: fix output bug in CHK macro<commit_after>#ifndef __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
#define __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__

#ifndef DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&);               \
  void operator=(const TypeName&)
#endif

#ifdef _DEBUG
#include "odbgstream.hpp"
#include "hrtext.hpp"
#include "iidstr.hpp"

// Simple trace logging macro that expands to nothing in release mode builds.
// Output is sent to the vs console.
#define DBGLOG(X) \
do { \
    wodbgstream wos; \
    wos << "["__FUNCTION__"] " << X << std::endl; \
} while(0)

// Extract error from the HRESULT, and output its hex and decimal values.
#define \
    HRLOG(X) L" {" << #X << L"=" << X << L"/" << std::hex << X << std::dec \
    << L" (" << hrtext(X) << L")}"

// Convert 100ns units to seconds
#define REFTIMETOSECONDS(X) (double(X) / 10000000.0f)

#else
#define DBGLOG(X)
#define REFTIMETOSECONDS(X)
#endif

// Keep the compiler quiet about do/while(0)'s (constant conditional) used in
// log macros.
#pragma warning(disable:4127)

// Check the HRESULT for failure (<0), and log it if we're in debug mode, and
// format the failure text so that it is clickable in vs output window.
#define CHK(X, Y) \
do { \
    if (FAILED(X=(Y))) \
    { \
        DBGLOG("\n" << __FILE__ << "(" << __LINE__ << ") : " << #Y << HRLOG(X)); \
    } \
} while (0)

#endif // __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
<|endoftext|>


<commit_before>#include "UnitWaveformMaker.h"

using namespace std;

struct UnitWaveformMaker::Parameters UnitWaveformMaker::params;

bool UnitWaveformMaker::makeUnitWaveform(const vector<double>& voice, bool is_vcv)
{
  return makeUnitWaveform(voice, -1, is_vcv);
}

bool UnitWaveformMaker::makeUnitWaveform(const vector<double>& voice, short pitch, bool is_vcv)
{
  this->voice = voice;
  if (voice.size()==0 || pitchmarks.empty() || params.num_lobes==0) {
    cerr << "[UnitWaveformMaker] voice, pitch mark or lobe is null" << endl;
    return false;
  }
  if (sub_ovrl > sub_fade_start) {
    cerr << "[UnitWaveformMaker] invalid ovrl and rep_start" << endl;
    return false;
  }
  double fade_start_rms = makeUnitWaveform(sub_fade_start, pitch).data.getRMS();

  // make unit waveforms
  {
    double fade_scale=1.0, ovrl_scale=1.0;
    vector<double> base_wav;
    if (params.normalize) {
      fade_scale = params.target_rms/fade_start_rms;
      ovrl_scale = is_vcv?((sub_ovrl>0)?params.target_rms/makeUnitWaveform(0, pitch).data.getRMS():1):fade_scale;
    }
    for (size_t i=0; i<pitchmarks.size()&&i<sub_fade_end; i++) {
      double scale = 1.0;
      // adjust uwc volume
      if (params.normalize) {
        if (is_vcv) {
          if (i > sub_ovrl && i < sub_fade_start) {
            double tmp = (i-sub_ovrl) / (double)(sub_fade_start-sub_ovrl);
            scale = (ovrl_scale*(1.0-tmp)) + (fade_scale*tmp);
          } else {
            scale = params.target_rms/makeUnitWaveform(i, pitch).data.getRMS();
          }
        } else {
          if (sub_ovrl==0 || i>=sub_fade_start) {
            scale = fade_scale;
          } else if (i <= sub_ovrl) {
            scale = ovrl_scale;
          } else {
            double tmp = (i-sub_ovrl) / (double)(sub_fade_start-sub_ovrl);
            scale = (ovrl_scale*(1.0-tmp)) + (fade_scale*tmp);
          }
        }
      }
      // make unit waveform
      uwc->unit_waveforms.push_back(makeUnitWaveform(i, pitch, scale));
      if (i > sub_fade_start+params.min_repeat_length) {
        if (base_wav.size() == 0) {
          base_wav = uwc->unit_waveforms[sub_fade_start].data.getData();
        }
        vector<double> target_wav = uwc->unit_waveforms.back().data.getData();
      }
    }
  }

  // make self fade
  {
    long sub_rep_len = (sub_fade_end-sub_fade_start) / 2;
    sub_fade_start = sub_fade_end - (sub_rep_len*2);
    for (size_t i=0; i<sub_rep_len; i++) {
      UnitWaveform uw_fore = uwc->unit_waveforms[sub_fade_start+i];
      UnitWaveform uw_aft = uwc->unit_waveforms[sub_fade_start+sub_rep_len+i];
      vector<double> data_fore = uw_fore.data.getData();
      vector<double> data_aft = uw_aft.data.getData();

      long left_diff = uw_aft.dwPitchLeft - uw_fore.dwPitchLeft;
      if (left_diff < 0) {
        data_fore.erase(data_fore.begin(), data_fore.begin()-left_diff);
      } else if (left_diff > 0) {
        data_fore.insert(data_fore.begin(), left_diff, 0);
      }
      long right_diff = uw_aft.dwPitchRight - uw_fore.dwPitchRight;
      if (right_diff < 0) {
        data_fore.erase(data_fore.end()+right_diff, data_fore.end());
      } else if (right_diff > 0) {
        data_fore.insert(data_fore.end(), right_diff, 0);
      }
      double scale = 1.0 / (sub_rep_len+1) * (i+1);
      for (size_t j=0; j<data_aft.size(); j++) {
        data_aft[j] = (data_fore[j]*scale) + (data_aft[j]*(1.0-scale));
      }
      uwc->unit_waveforms[sub_fade_start+sub_rep_len+i].data.setData(data_aft);
    }
    uwc->header.dwRepeatStart = sub_fade_start + sub_rep_len;
  }

  return true;
}

/*
 * accessor
 */
const vector<long>& UnitWaveformMaker::getPitchMarks() const
{
  return pitchmarks;
}

void UnitWaveformMaker::setOvrl(long ms_ovrl, unsigned long fs)
{
  long pos_ovrl = ms_ovrl * fs / 1000;
  for (size_t i=0; i<pitchmarks.size(); i++) {
    if (pos_ovrl <= pitchmarks[i]) {
      sub_ovrl = i;
      break;
    }
  }
}

void UnitWaveformMaker::setOvrl(long sub_ovrl)
{
  this->sub_ovrl = sub_ovrl;
}

void UnitWaveformMaker::setFadeParams(long ms_fade_start, long ms_fade_end, unsigned long fs)
{
  long pos_fade_start = ms_fade_start * fs / 1000;
  for (size_t i=0; i<pitchmarks.size(); i++) {
    if (pos_fade_start <= pitchmarks[i]) {
      sub_fade_start = i;
      break;
    }
  }
  long pos_fade_end = ms_fade_end * fs / 1000;
  if (pos_fade_end>pitchmarks.back() || ms_fade_start>ms_fade_end) {
    sub_fade_end = pitchmarks.size()-1;
  } else {
    for (size_t i=0; i<pitchmarks.size(); i++) {
      if (pos_fade_end <= pitchmarks[i]) {
        ms_fade_end = i;
        break;
      }
    }
  }
}

void UnitWaveformMaker::setFadeParams(long sub_fade_start, long sub_fade_end)
{
  this->sub_fade_start = sub_fade_start;
  this->sub_fade_end = sub_fade_end;
}

/*
 * private
 */
UnitWaveform UnitWaveformMaker::makeUnitWaveform(short point, short pitch)
{
  return makeUnitWaveform(point, pitch, 1.0);
}

UnitWaveform UnitWaveformMaker::makeUnitWaveform(short point, short pitch, double scale)
{
  // cut window out
  UnitWaveform unit_waveform;
  if (pitch <= 0) {
    pitch = (point>=pitchmarks.size()-1)?pitchmarks.back()-(*----pitchmarks.end()):pitchmarks[point+1]-pitchmarks[point];
  }
  long win_start = pitchmarks[point] - (pitch*params.num_lobes);
  long win_end = pitchmarks[point] + (pitch*params.num_lobes);
  vector<double> filter = getWindow(pitch*params.num_lobes*2+1, params.num_lobes);
  unit_waveform.dwPitchLeft = unit_waveform.dwPitchRight = pitch * params.num_lobes;
  unit_waveform.dwPosition = pitchmarks[point] - pitchmarks[0];

  // set unit waveform data
  vector<double> unit_waveform_data(win_end-win_start+1, 0);
  for (long i=0; i<unit_waveform_data.size(); i++) {
    unit_waveform_data[i] = (win_start+i<0 || win_start+i>=voice.size())?0:(voice[win_start+i]*filter[i])*scale;
  }
  unit_waveform.data.setData(unit_waveform_data);

  return unit_waveform;
}
<commit_msg>scale bugfix at unit waveform maker<commit_after>#include "UnitWaveformMaker.h"

using namespace std;

struct UnitWaveformMaker::Parameters UnitWaveformMaker::params;

bool UnitWaveformMaker::makeUnitWaveform(const vector<double>& voice, bool is_vcv)
{
  return makeUnitWaveform(voice, -1, is_vcv);
}

bool UnitWaveformMaker::makeUnitWaveform(const vector<double>& voice, short pitch, bool is_vcv)
{
  this->voice = voice;
  if (voice.size()==0 || pitchmarks.empty() || params.num_lobes==0) {
    cerr << "[UnitWaveformMaker] voice, pitch mark or lobe is null" << endl;
    return false;
  }
  if (sub_ovrl > sub_fade_start) {
    cerr << "[UnitWaveformMaker] invalid ovrl and rep_start" << endl;
    return false;
  }
  double fade_start_rms = makeUnitWaveform(sub_fade_start, pitch).data.getRMS();

  // make unit waveforms
  {
    double fade_scale=1.0, ovrl_scale=1.0;
    vector<double> base_wav;
    if (params.normalize) {
      fade_scale = params.target_rms/fade_start_rms;
      ovrl_scale = is_vcv?((sub_ovrl>0)?params.target_rms/makeUnitWaveform(0, pitch).data.getRMS():1):fade_scale;
    }
    for (size_t i=0; i<pitchmarks.size()&&i<sub_fade_end; i++) {
      double scale = 1.0;
      // adjust uwc volume
      if (params.normalize) {
        if (is_vcv) {
          if (i > sub_ovrl && i < sub_fade_start) {
            double tmp = (i-sub_ovrl) / (double)(sub_fade_start-sub_ovrl);
            scale = (ovrl_scale*(1.0-tmp)) + (fade_scale*tmp);
          } else if (i <= sub_ovrl) {
            scale = ovrl_scale;
          } else {
            scale = fade_scale;
          }
        } else {
          if (sub_ovrl==0 || i>=sub_fade_start) {
            scale = fade_scale;
          } else if (i <= sub_ovrl) {
            scale = ovrl_scale;
          } else {
            double tmp = (i-sub_ovrl) / (double)(sub_fade_start-sub_ovrl);
            scale = (ovrl_scale*(1.0-tmp)) + (fade_scale*tmp);
          }
        }
      }
      // make unit waveform
      uwc->unit_waveforms.push_back(makeUnitWaveform(i, pitch, scale));
      if (i > sub_fade_start+params.min_repeat_length) {
        if (base_wav.size() == 0) {
          base_wav = uwc->unit_waveforms[sub_fade_start].data.getData();
        }
        vector<double> target_wav = uwc->unit_waveforms.back().data.getData();
      }
    }
  }

  // make self fade
  {
    long sub_rep_len = (sub_fade_end-sub_fade_start) / 2;
    sub_fade_start = sub_fade_end - (sub_rep_len*2);
    for (size_t i=0; i<sub_rep_len; i++) {
      UnitWaveform uw_fore = uwc->unit_waveforms[sub_fade_start+i];
      UnitWaveform uw_aft = uwc->unit_waveforms[sub_fade_start+sub_rep_len+i];
      vector<double> data_fore = uw_fore.data.getData();
      vector<double> data_aft = uw_aft.data.getData();

      long left_diff = uw_aft.dwPitchLeft - uw_fore.dwPitchLeft;
      if (left_diff < 0) {
        data_fore.erase(data_fore.begin(), data_fore.begin()-left_diff);
      } else if (left_diff > 0) {
        data_fore.insert(data_fore.begin(), left_diff, 0);
      }
      long right_diff = uw_aft.dwPitchRight - uw_fore.dwPitchRight;
      if (right_diff < 0) {
        data_fore.erase(data_fore.end()+right_diff, data_fore.end());
      } else if (right_diff > 0) {
        data_fore.insert(data_fore.end(), right_diff, 0);
      }
      double scale = 1.0 / (sub_rep_len+1) * (i+1);
      for (size_t j=0; j<data_aft.size(); j++) {
        data_aft[j] = (data_fore[j]*scale) + (data_aft[j]*(1.0-scale));
      }
      uwc->unit_waveforms[sub_fade_start+sub_rep_len+i].data.setData(data_aft);
    }
    uwc->header.dwRepeatStart = sub_fade_start + sub_rep_len;
  }

  return true;
}

/*
 * accessor
 */
const vector<long>& UnitWaveformMaker::getPitchMarks() const
{
  return pitchmarks;
}

void UnitWaveformMaker::setOvrl(long ms_ovrl, unsigned long fs)
{
  long pos_ovrl = ms_ovrl * fs / 1000;
  for (size_t i=0; i<pitchmarks.size(); i++) {
    if (pos_ovrl <= pitchmarks[i]) {
      sub_ovrl = i;
      break;
    }
  }
}

void UnitWaveformMaker::setOvrl(long sub_ovrl)
{
  this->sub_ovrl = sub_ovrl;
}

void UnitWaveformMaker::setFadeParams(long ms_fade_start, long ms_fade_end, unsigned long fs)
{
  long pos_fade_start = ms_fade_start * fs / 1000;
  for (size_t i=0; i<pitchmarks.size(); i++) {
    if (pos_fade_start <= pitchmarks[i]) {
      sub_fade_start = i;
      break;
    }
  }
  long pos_fade_end = ms_fade_end * fs / 1000;
  if (pos_fade_end>pitchmarks.back() || ms_fade_start>ms_fade_end) {
    sub_fade_end = pitchmarks.size()-1;
  } else {
    for (size_t i=0; i<pitchmarks.size(); i++) {
      if (pos_fade_end <= pitchmarks[i]) {
        ms_fade_end = i;
        break;
      }
    }
  }
}

void UnitWaveformMaker::setFadeParams(long sub_fade_start, long sub_fade_end)
{
  this->sub_fade_start = sub_fade_start;
  this->sub_fade_end = sub_fade_end;
}

/*
 * private
 */
UnitWaveform UnitWaveformMaker::makeUnitWaveform(short point, short pitch)
{
  return makeUnitWaveform(point, pitch, 1.0);
}

UnitWaveform UnitWaveformMaker::makeUnitWaveform(short point, short pitch, double scale)
{
  // cut window out
  UnitWaveform unit_waveform;
  if (pitch <= 0) {
    pitch = (point>=pitchmarks.size()-1)?pitchmarks.back()-(*----pitchmarks.end()):pitchmarks[point+1]-pitchmarks[point];
  }
  long win_start = pitchmarks[point] - (pitch*params.num_lobes);
  long win_end = pitchmarks[point] + (pitch*params.num_lobes);
  vector<double> filter = getWindow(pitch*params.num_lobes*2+1, params.num_lobes);
  unit_waveform.dwPitchLeft = unit_waveform.dwPitchRight = pitch * params.num_lobes;
  unit_waveform.dwPosition = pitchmarks[point] - pitchmarks[0];

  // set unit waveform data
  vector<double> unit_waveform_data(win_end-win_start+1, 0);
  for (long i=0; i<unit_waveform_data.size(); i++) {
    unit_waveform_data[i] = (win_start+i<0 || win_start+i>=voice.size())?0:(voice[win_start+i]*filter[i])*scale;
  }
  unit_waveform.data.setData(unit_waveform_data);

  return unit_waveform;
}
<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "cinder/Capture.h"
#include "cinder/gl/Texture.h"
#include "cinder/gl/GlslProg.h"
#include "cinder/Log.h"
#include "cinder/gl/Fbo.h"
#include "cinder/gl/Shader.h"

#include "GridTexture.h"
#include "Landscape.h"
#include "IntroSequence.h"

#include "cinder/MotionManager.h"
#include "cinder/Timeline.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace soso;

struct TouchInfo {
	TouchInfo() = default;
	TouchInfo( uint32_t iId, const vec2 &iStart, const vec2 &iPosition )
	: id( iId ),
		previous( iStart ),
		position( iPosition )
	{}

  uint32_t		id = 0;
  vec2				previous;
  vec2				position;
};

class SelfieSelfieApp : public App {
public:
	void setup() override;
	void update() override;
	void draw() override;

  void touchesBegan( TouchEvent event ) override;
  void touchesMoved( TouchEvent event ) override;
  void touchesEnded( TouchEvent event ) override;

	void updateCamera();
	void showLandscape();

private:
	CameraPersp				camera;
  CaptureRef				capture;

  GridTextureRef		gridTexture;
  Landscape					landscape;
	gl::BatchRef			cameraImage;
	IntroSequence			introduction;

  vector<TouchInfo> touches;
  ci::vec3					cameraOffset;
	float							cameraVelocity = 0.0f;

  bool							drawDebug = false;

	ci::Anim<float>		cameraWeight = 0.0f;
	quat							startOrientation;
};

void SelfieSelfieApp::setup()
{
  CI_LOG_I("Setting up selfie_x_selfie");

  MotionManager::enable();

  GLint size;
  glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );
  CI_LOG_I( "Max texture size: " << size );

  auto target = vec3( 5, 0, 0 );
  camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
  camera.setPerspective( 80, getWindowAspectRatio(), 0.1f, 50.0f );
	startOrientation = camera.getOrientation();

  try {
    CI_LOG_I( "Initializing hardware camera." );
    auto front_facing_camera = ([] {
      auto &devices = Capture::getDevices();
      auto first_device = devices.front();
      for( auto device : devices ) {
        if( device->isFrontFacing() ) {
          return device;
        }
      }
      return first_device;
    }());

		#if defined(CINDER_ANDROID)
			capture = Capture::create( 640, 480, front_facing_camera );
		#else
    	capture = Capture::create( 480, 360, front_facing_camera );
    #endif
    capture->start();

    CI_LOG_I( "Creating Grid Texture" );
    gridTexture = make_shared<GridTexture>( ivec2( 320, 240 ), 12 );

    CI_LOG_I( "Setting up landscape geometry." );
    landscape.setup();
    landscape.setTextureUnits( 0, 1 );
    landscape.setGridSize( gridTexture->getGridDimensions() );
  }
  catch( ci::Exception &exc ) {
    CI_LOG_E( "Error using device camera: " << exc.what() );
  }

	introduction.setup( getAssetPath( "intro/5" ) );
	introduction.setFinishFn( [this] { showLandscape(); } );
}

void SelfieSelfieApp::touchesBegan( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    touches.emplace_back( t.getId(), t.getPos(), t.getPos() );
  }

  if( touches.size() == 4 ) {
    drawDebug = ! drawDebug;
  }
}

void SelfieSelfieApp::touchesMoved( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    for( auto &s : touches ) {
      if( s.id == t.getId() ) {
				s.previous = s.position;
        s.position = t.getPos();
      }
    }
  }
}

void SelfieSelfieApp::touchesEnded( TouchEvent event )
{
  touches.erase( std::remove_if( touches.begin(), touches.end(), [&event] (const TouchInfo &s) {
    for( auto &t : event.getTouches() ) {
      if (t.getId() == s.id) {
        return true;
      }
    }
    return false;
  }), touches.end() );
}

void SelfieSelfieApp::showLandscape()
{
	// Enable looking around with the gyro
	timeline().apply( &cameraWeight, 1.0f, 1.33f ).easeFn( EaseInOutCubic() );
}

void SelfieSelfieApp::update()
{
	introduction.update();
	updateCamera();

  if( capture && capture->checkNewFrame() ) {
    gridTexture->update( *capture->getSurface() );
  }
}

void SelfieSelfieApp::updateCamera()
{
	if( touches.size() == 1 )
	{
		const auto forward = ([] {
			auto gravity = MotionManager::getGravityDirection();
			if( abs( gravity.x ) > abs( gravity.y ) ) {
				auto x = copysign( 1.0f, gravity.x );
				return vec3( x, 0, 0 );
			}
			else {
				auto y = copysign( 1.0f, gravity.y );
				return vec3( 0, - y, 0 );
			}
		}());

		auto &touch = touches.front();
		auto delta = vec3( touch.position - touch.previous, 0 );
		touch.previous = touch.position;

		auto amount = length( delta );
		auto dir = dot( normalize(delta), forward );

		if( isfinite( amount ) && isfinite( dir ) ) {
			cameraVelocity += amount * dir;
		}
	}

	auto ray = camera.getViewDirection();
	cameraOffset += ray * cameraVelocity * 0.0025f;
	cameraVelocity *= 0.86f;

	auto l = length(cameraOffset);
	auto maximum = 2.7f;
	if( l > maximum ) {
		cameraOffset *= (maximum / l);
	}
	camera.setEyePoint( cameraOffset );

	auto r = glm::slerp( startOrientation, MotionManager::getRotation(), cameraWeight.value() );
	camera.setOrientation( r );
}

void SelfieSelfieApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );

  {
    gl::enableDepthRead();
    gl::enableDepthWrite();
		gl::ScopedGlslProg prog( gl::getStockShader( gl::ShaderDef().texture(gridTexture->getTexture()->getTarget()) ) );

    gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );
    gl::ScopedTextureBind tex1( gridTexture->getBlurredTexture(), 1 );
    gl::ScopedMatrices matrices;
    gl::setMatrices( camera );

		landscape.draw( gridTexture->getCurrentIndex() );

		auto mat = translate( vec3( 0, -4.0f, 0 ) );
		auto dims = vec2(gridTexture->getCellDimensions()) / gridTexture->getGridSize();
		auto offset = vec2(gridTexture->getIndexOffset( gridTexture->getCellDimensions(), gridTexture->getCurrentIndex() )) / gridTexture->getGridSize();
		auto rect = Rectf( -1.0f, -1.0f, 1.0f, 1.0f ).scaled( vec2( 1.333f, 1.0f ) ).scaled( 0.2f );
		auto half_pi = (float) M_PI / 2.0f;
		auto xf1 = translate( vec3( - 12.0f, 0.0f, 0.0f ) ) * rotate( - half_pi, vec3( 1, 0, 0 ) ) * rotate( half_pi, vec3( 0, 1, 0 ) );
		auto xf2 = translate( vec3( 4.0f, 0.0f, 0.0f ) ) * rotate( half_pi, vec3( 1, 0, 0 ) ) * rotate( - half_pi, vec3( 0, 1, 0 ) );

		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf1 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf2 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

  }

  gl::disableDepthRead();

	gl::ScopedMatrices matrices;
	gl::setMatricesWindow( getWindowSize() );
	introduction.draw();

  if( drawDebug && gridTexture )
  {
    auto rect = Rectf(gridTexture->getTexture()->getBounds());
    auto window_rect = Rectf(getWindowBounds());
    auto window_rect_a = window_rect.scaled( vec2( 0.5f ) );
    auto window_rect_b = window_rect_a + vec2( window_rect_a.getWidth(), 0 );
    gl::draw( gridTexture->getTexture(), rect.getCenteredFit( window_rect_a, false ) );
    gl::draw( gridTexture->getBlurredTexture(), rect.getCenteredFit( window_rect_b, false ) );
  }

  /*
  // For confirming version changes, draw a different colored dot.
  gl::ScopedColor color( Color( 0.0f, 0.0f, 1.0f ) );
  gl::drawSolidCircle( vec2( 20.0f ), 10.0f );
  //*/

  auto err = gl::getError();
  if( err ) {
    CI_LOG_E( "Draw gl error: " << gl::getErrorString(err) );
  }
}

inline void prepareSettings( app::App::Settings *iSettings )
{
  iSettings->setMultiTouchEnabled();
	iSettings->setHighDensityDisplayEnabled();
}

CINDER_APP( SelfieSelfieApp, RendererGl, &prepareSettings )
<commit_msg>Zoom camera full view.<commit_after>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "cinder/Capture.h"
#include "cinder/gl/Texture.h"
#include "cinder/gl/GlslProg.h"
#include "cinder/Log.h"
#include "cinder/gl/Fbo.h"
#include "cinder/gl/Shader.h"

#include "GridTexture.h"
#include "Landscape.h"
#include "IntroSequence.h"

#include "cinder/MotionManager.h"
#include "cinder/Timeline.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace soso;

struct TouchInfo {
	TouchInfo() = default;
	TouchInfo( uint32_t iId, const vec2 &iStart, const vec2 &iPosition )
	: id( iId ),
		previous( iStart ),
		position( iPosition )
	{}

  uint32_t		id = 0;
  vec2				previous;
  vec2				position;
};

class SelfieSelfieApp : public App {
public:
	void setup() override;
	void update() override;
	void draw() override;

  void touchesBegan( TouchEvent event ) override;
  void touchesMoved( TouchEvent event ) override;
  void touchesEnded( TouchEvent event ) override;

	void updateCamera();
	void showLandscape();

private:
	CameraPersp				camera;
  CaptureRef				capture;

  GridTextureRef		gridTexture;
  Landscape					landscape;
	gl::BatchRef			cameraImage;
	IntroSequence			introduction;

  vector<TouchInfo> touches;
  ci::vec3					cameraOffset;
	float							cameraVelocity = 0.0f;

  bool							drawDebug = false;

	ci::Anim<float>			cameraWeight = 0.0f;
	ci::Anim<ci::vec3>	cameraEyePoint = ci::vec3( 3.8f, 0.0f, 0.0f );
	quat								startOrientation;
};

void SelfieSelfieApp::setup()
{
  CI_LOG_I("Setting up selfie_x_selfie");

  MotionManager::enable();

  GLint size;
  glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );
  CI_LOG_I( "Max texture size: " << size );

  auto target = vec3( 5, 0, 0 );
  camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
  camera.setPerspective( 80, getWindowAspectRatio(), 0.1f, 50.0f );
	startOrientation = camera.getOrientation();

  try {
    CI_LOG_I( "Initializing hardware camera." );
    auto front_facing_camera = ([] {
      auto &devices = Capture::getDevices();
      auto first_device = devices.front();
      for( auto device : devices ) {
        if( device->isFrontFacing() ) {
          return device;
        }
      }
      return first_device;
    }());

		#if defined(CINDER_ANDROID)
			capture = Capture::create( 640, 480, front_facing_camera );
		#else
    	capture = Capture::create( 480, 360, front_facing_camera );
    #endif
    capture->start();

    CI_LOG_I( "Creating Grid Texture" );
    gridTexture = make_shared<GridTexture>( ivec2( 320, 240 ), 12 );

    CI_LOG_I( "Setting up landscape geometry." );
    landscape.setup();
    landscape.setTextureUnits( 0, 1 );
    landscape.setGridSize( gridTexture->getGridDimensions() );
  }
  catch( ci::Exception &exc ) {
    CI_LOG_E( "Error using device camera: " << exc.what() );
  }

	introduction.setup( getAssetPath( "intro/5" ) );
	introduction.setFinishFn( [this] { showLandscape(); } );
}

void SelfieSelfieApp::touchesBegan( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    touches.emplace_back( t.getId(), t.getPos(), t.getPos() );
  }

  if( touches.size() == 4 ) {
    drawDebug = ! drawDebug;
  }
}

void SelfieSelfieApp::touchesMoved( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    for( auto &s : touches ) {
      if( s.id == t.getId() ) {
				s.previous = s.position;
        s.position = t.getPos();
      }
    }
  }
}

void SelfieSelfieApp::touchesEnded( TouchEvent event )
{
  touches.erase( std::remove_if( touches.begin(), touches.end(), [&event] (const TouchInfo &s) {
    for( auto &t : event.getTouches() ) {
      if (t.getId() == s.id) {
        return true;
      }
    }
    return false;
  }), touches.end() );
}

void SelfieSelfieApp::showLandscape()
{
	// Enable looking around with the gyro
	float zoom = 4.0f;
	timeline().apply( &cameraEyePoint, vec3( 0 ), zoom ).easeFn( EaseInOutCubic() );
	timeline().apply( &cameraWeight, 1.0f, 1.33f ).easeFn( EaseInOutCubic() ).delay( zoom );
}

void SelfieSelfieApp::update()
{
	introduction.update();
	updateCamera();

  if( capture && capture->checkNewFrame() ) {
    gridTexture->update( *capture->getSurface() );
  }
}

void SelfieSelfieApp::updateCamera()
{
	if( touches.size() == 1 )
	{
		const auto forward = ([] {
			auto gravity = MotionManager::getGravityDirection();
			if( abs( gravity.x ) > abs( gravity.y ) ) {
				auto x = copysign( 1.0f, gravity.x );
				return vec3( x, 0, 0 );
			}
			else {
				auto y = copysign( 1.0f, gravity.y );
				return vec3( 0, - y, 0 );
			}
		}());

		auto &touch = touches.front();
		auto delta = vec3( touch.position - touch.previous, 0 );
		touch.previous = touch.position;

		auto amount = length( delta );
		auto dir = dot( normalize(delta), forward );

		if( isfinite( amount ) && isfinite( dir ) ) {
			cameraVelocity += amount * dir;
		}
	}

	auto ray = camera.getViewDirection();
	cameraVelocity *= cameraWeight.value();
	cameraOffset += ray * cameraVelocity * 0.0025f;
	cameraVelocity *= 0.86f;

	auto l = length(cameraOffset);
	auto maximum = 2.5f;
	if( l > maximum ) {
		cameraOffset *= (maximum / l);
	}
	camera.setEyePoint( cameraEyePoint() + cameraOffset );

	auto r = glm::slerp( startOrientation, MotionManager::getRotation(), cameraWeight.value() );
	camera.setOrientation( r );
}

void SelfieSelfieApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );

  {
    gl::enableDepthRead();
    gl::enableDepthWrite();
		gl::ScopedGlslProg prog( gl::getStockShader( gl::ShaderDef().texture(gridTexture->getTexture()->getTarget()) ) );

    gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );
    gl::ScopedTextureBind tex1( gridTexture->getBlurredTexture(), 1 );
    gl::ScopedMatrices matrices;
    gl::setMatrices( camera );

		landscape.draw( gridTexture->getCurrentIndex() );

		auto mat = translate( vec3( 0, -4.0f, 0 ) );
		auto dims = vec2(gridTexture->getCellDimensions()) / gridTexture->getGridSize();
		auto offset = vec2(gridTexture->getIndexOffset( gridTexture->getCellDimensions(), gridTexture->getCurrentIndex() )) / gridTexture->getGridSize();
		auto rect = Rectf( -1.0f, -1.0f, 1.0f, 1.0f ).scaled( vec2( 1.333f, 1.0f ) ).scaled( 0.2f );
		auto half_pi = (float) M_PI / 2.0f;
		auto xf1 = translate( vec3( - 12.0f, 0.0f, 0.0f ) ) * rotate( - half_pi, vec3( 1, 0, 0 ) ) * rotate( half_pi, vec3( 0, 1, 0 ) );
		auto xf2 = translate( vec3( 4.0f, 0.0f, 0.0f ) ) * rotate( half_pi, vec3( 1, 0, 0 ) ) * rotate( - half_pi, vec3( 0, 1, 0 ) );

		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf1 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf2 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

  }

  gl::disableDepthRead();

	gl::ScopedMatrices matrices;
	gl::setMatricesWindow( getWindowSize() );
	introduction.draw();

  if( drawDebug && gridTexture )
  {
    auto rect = Rectf(gridTexture->getTexture()->getBounds());
    auto window_rect = Rectf(getWindowBounds());
    auto window_rect_a = window_rect.scaled( vec2( 0.5f ) );
    auto window_rect_b = window_rect_a + vec2( window_rect_a.getWidth(), 0 );
    gl::draw( gridTexture->getTexture(), rect.getCenteredFit( window_rect_a, false ) );
    gl::draw( gridTexture->getBlurredTexture(), rect.getCenteredFit( window_rect_b, false ) );
  }

  /*
  // For confirming version changes, draw a different colored dot.
  gl::ScopedColor color( Color( 0.0f, 0.0f, 1.0f ) );
  gl::drawSolidCircle( vec2( 20.0f ), 10.0f );
  //*/

  auto err = gl::getError();
  if( err ) {
    CI_LOG_E( "Draw gl error: " << gl::getErrorString(err) );
  }
}

inline void prepareSettings( app::App::Settings *iSettings )
{
  iSettings->setMultiTouchEnabled();
	iSettings->setHighDensityDisplayEnabled();
}

CINDER_APP( SelfieSelfieApp, RendererGl, &prepareSettings )
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "drivers/Timer.h"
#include "hal/ticker_api.h"
#include "hal/us_ticker_api.h"
#include "platform/mbed_critical.h"
#include "hal/lp_ticker_api.h"

namespace mbed {

Timer::Timer() : _running(), _start(), _time(), _ticker_data(get_us_ticker_data()), _lock_deepsleep(true) {
    reset();
}

Timer::Timer(const ticker_data_t *data) : _running(), _start(), _time(), _ticker_data(data), _lock_deepsleep(true) {
    reset();
#if DEVICE_LOWPOWERTIMER
    _lock_deepsleep = (data != get_lp_ticker_data());
#endif
}

Timer::~Timer() {
    core_util_critical_section_enter();
    if (_running) {
        sleep_manager_unlock_deep_sleep();
    }
    _running = 0;
    core_util_critical_section_exit();
}

void Timer::start() {
    core_util_critical_section_enter();
    if (!_running) {
        if(_lock_deepsleep) {
            sleep_manager_lock_deep_sleep();
        }
        _start = ticker_read_us(_ticker_data);
        _running = 1;
    }
    core_util_critical_section_exit();
}

void Timer::stop() {
    core_util_critical_section_enter();
    _time += slicetime();
    if (_running) {
        if(_lock_deepsleep) {
            sleep_manager_unlock_deep_sleep();
        }
    }
    _running = 0;
    core_util_critical_section_exit();
}

int Timer::read_us() {
    return read_high_resolution_us();
}

float Timer::read() {
    return (float)read_us() / 1000000.0f;
}

int Timer::read_ms() {
    return read_high_resolution_us() / 1000;
}

us_timestamp_t Timer::read_high_resolution_us() {
    core_util_critical_section_enter();
    us_timestamp_t time = _time + slicetime();
    core_util_critical_section_exit();
    return time;
}

us_timestamp_t Timer::slicetime() {
    us_timestamp_t ret = 0;
    core_util_critical_section_enter();
    if (_running) {
        ret = ticker_read_us(_ticker_data) - _start;
    }
    core_util_critical_section_exit();
    return ret;
}

void Timer::reset() {
    core_util_critical_section_enter();
    _start = ticker_read_us(_ticker_data);
    _time = 0;
    core_util_critical_section_exit();
}

Timer::operator float() {
    return read();
}

} // namespace mbed
<commit_msg>Fix sleep lock underflow in LowPowerTimer<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "drivers/Timer.h"
#include "hal/ticker_api.h"
#include "hal/us_ticker_api.h"
#include "platform/mbed_critical.h"
#include "hal/lp_ticker_api.h"

namespace mbed {

Timer::Timer() : _running(), _start(), _time(), _ticker_data(get_us_ticker_data()), _lock_deepsleep(true) {
    reset();
}

Timer::Timer(const ticker_data_t *data) : _running(), _start(), _time(), _ticker_data(data), _lock_deepsleep(true) {
    reset();
#if DEVICE_LOWPOWERTIMER
    _lock_deepsleep = (data != get_lp_ticker_data());
#endif
}

Timer::~Timer() {
    core_util_critical_section_enter();
    if (_running) {
        if(_lock_deepsleep) {
            sleep_manager_unlock_deep_sleep();
        }
    }
    _running = 0;
    core_util_critical_section_exit();
}

void Timer::start() {
    core_util_critical_section_enter();
    if (!_running) {
        if(_lock_deepsleep) {
            sleep_manager_lock_deep_sleep();
        }
        _start = ticker_read_us(_ticker_data);
        _running = 1;
    }
    core_util_critical_section_exit();
}

void Timer::stop() {
    core_util_critical_section_enter();
    _time += slicetime();
    if (_running) {
        if(_lock_deepsleep) {
            sleep_manager_unlock_deep_sleep();
        }
    }
    _running = 0;
    core_util_critical_section_exit();
}

int Timer::read_us() {
    return read_high_resolution_us();
}

float Timer::read() {
    return (float)read_us() / 1000000.0f;
}

int Timer::read_ms() {
    return read_high_resolution_us() / 1000;
}

us_timestamp_t Timer::read_high_resolution_us() {
    core_util_critical_section_enter();
    us_timestamp_t time = _time + slicetime();
    core_util_critical_section_exit();
    return time;
}

us_timestamp_t Timer::slicetime() {
    us_timestamp_t ret = 0;
    core_util_critical_section_enter();
    if (_running) {
        ret = ticker_read_us(_ticker_data) - _start;
    }
    core_util_critical_section_exit();
    return ret;
}

void Timer::reset() {
    core_util_critical_section_enter();
    _start = ticker_read_us(_ticker_data);
    _time = 0;
    core_util_critical_section_exit();
}

Timer::operator float() {
    return read();
}

} // namespace mbed
<|endoftext|>


<commit_before>#include "HM3Hooks.h"

#include <detours.h>

struct DetourAddresses
{
	uint32_t LoadSceneDetour;
	uint32_t UnknownUpdateDetour;
	uint32_t EndLevelDetour;
	uint32_t LimitedLivesDetour
};

// The order corresponds to HM3Version enum values and should not be changed
static const DetourAddresses DetourVersions[]
{
	{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, // Unknown version
	{ 0x0045A440, 0x006AF230, 0x006AEC80, 0x00677660 }, // Steam
	{ 0x00000000, 0x006AFAF0, 0x00000000, 0x00000000 }  // GOG
};

HM3Hooks::HM3Hooks(HM3Version version)
{
	Install(version);
}

HM3Hooks::~HM3Hooks()
{

}

void HM3Hooks::Install(HM3Version version)
{
	const DetourAddresses& addresses(DetourVersions[version]);

	LoadScene = addresses.LoadSceneDetour != 0 ? (LoadScene_t) DetourFunction((PBYTE) addresses.LoadSceneDetour, (PBYTE) c_LoadScene) : nullptr;
	UnknownUpdateFunc01 = addresses.UnknownUpdateDetour != 0 ? (UnknownUpdateFunc01_t) DetourFunction((PBYTE) addresses.UnknownUpdateDetour, (PBYTE) c_UnknownUpdateFunc01) : nullptr;
	EndLevel = addresses.EndLevelDetour != 0 ? (EndLevel_t) DetourFunction((PBYTE) addresses.EndLevelDetour, (PBYTE) c_EndLevel) : nullptr;
	LimitedLives_SelectedGUIElement = addresses.LimitedLivesDetour != 0 ? (LimitedLives_SelectedGUIElement_t) DetourFunction((PBYTE) addresses.LimitedLivesDetour, (PBYTE) c_LimitedLives_SelectedGUIElement) : nullptr;
}<commit_msg>Fix Syntax<commit_after>#include "HM3Hooks.h"

#include <detours.h>

struct DetourAddresses
{
	uint32_t LoadSceneDetour;
	uint32_t UnknownUpdateDetour;
	uint32_t EndLevelDetour;
	uint32_t LimitedLivesDetour;
};

// The order corresponds to HM3Version enum values and should not be changed
static const DetourAddresses DetourVersions[]
{
	{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, // Unknown version
	{ 0x0045A440, 0x006AF230, 0x006AEC80, 0x00677660 }, // Steam
	{ 0x00000000, 0x006AFAF0, 0x00000000, 0x00000000 }  // GOG
};

HM3Hooks::HM3Hooks(HM3Version version)
{
	Install(version);
}

HM3Hooks::~HM3Hooks()
{

}

void HM3Hooks::Install(HM3Version version)
{
	const DetourAddresses& addresses(DetourVersions[version]);

	LoadScene = addresses.LoadSceneDetour != 0 ? (LoadScene_t) DetourFunction((PBYTE) addresses.LoadSceneDetour, (PBYTE) c_LoadScene) : nullptr;
	UnknownUpdateFunc01 = addresses.UnknownUpdateDetour != 0 ? (UnknownUpdateFunc01_t) DetourFunction((PBYTE) addresses.UnknownUpdateDetour, (PBYTE) c_UnknownUpdateFunc01) : nullptr;
	EndLevel = addresses.EndLevelDetour != 0 ? (EndLevel_t) DetourFunction((PBYTE) addresses.EndLevelDetour, (PBYTE) c_EndLevel) : nullptr;
	LimitedLives_SelectedGUIElement = addresses.LimitedLivesDetour != 0 ? (LimitedLives_SelectedGUIElement_t) DetourFunction((PBYTE) addresses.LimitedLivesDetour, (PBYTE) c_LimitedLives_SelectedGUIElement) : nullptr;
}<|endoftext|>