<commit_before>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2001, 2004 Anders Lund <anders.lund@lund.tdcadsl.dk>
   Copyright (C) 2007-2008 Dominik Haumann <dhaumann kde org>
   Copyright (C) 2007 Flavio Castelli <flavio.castelli@gmail.com>
   Copyright (C) 2008 Eduardo Robles Elvira <edulix@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "katefinddialog.h"
#include "katefindinfiles.h"
#include "kateresultview.h"
#include "katefindoptions.h"

#include <ktexteditor/document.h>
#include <ktexteditor/view.h>

#include <kdebug.h>

#include <QClipboard>
#include <QRegExp>
#include <QShowEvent>
#include <QLineEdit>

#include <kacceleratormanager.h>
#include <kconfig.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kurlcompletion.h>

KateFindDialog::KateFindDialog(Kate::MainWindow *mw, KateFindInFilesView *view)
    : KDialog(mw->window()), m_mw (mw), m_view(view)
    , m_useId(-1)
{
  setCaption(i18n("Find in Files"));
  setButtons(Close | User1);

  setButtonGuiItem(User1, KStandardGuiItem::find());
  setDefaultButton(User1);

  QWidget* widget = new QWidget(this);
  setupUi(widget);
  setMainWidget(widget);

  // if possible, ui properties are set in the .ui-file

  // set sync icon
  btnSync->setIcon(KIcon("view-refresh"));

  // get url-requester's combo box and sanely initialize
  KComboBox* cmbUrl = cmbDir->comboBox();
  cmbUrl->setDuplicatesEnabled(false);
  cmbUrl->setEditable(true);
  cmbDir->setMode( KFile::Directory | KFile::LocalOnly );
  KUrlCompletion* cmpl = new KUrlCompletion(KUrlCompletion::DirCompletion);
  cmbUrl->setCompletionObject( cmpl );
  cmbUrl->setAutoDeleteCompletionObject( true );

  updateItems();
  syncDir();

  // auto-accels
  KAcceleratorManager::manage( this );

  lblPattern->setWhatsThis( i18n("
Enter the expression you want to search for here.
"
                                 "
If 'regular expression' is unchecked, any non-space letters in your "
                                 "expression will be escaped with a backslash character.
"
                                 "
Possible meta characters are:
"
                                 ". - Matches any character
"
                                 "^ - Matches the beginning of a line
"
                                 "$ - Matches the end of a line
"
                                 "\\< - Matches the beginning of a word
"
                                 "\\> - Matches the end of a word
"
                                 "
The following repetition operators exist:
"
                                 "? - The preceding item is matched at most once
"
                                 "* - The preceding item is matched zero or more times
"
                                 "+ - The preceding item is matched one or more times
"
                                 "{n} - The preceding item is matched exactly n times
"
                                 "{n,} - The preceding item is matched n or more times
"
                                 "{,n} - The preceding item is matched at most n times
"
                                 "{n,m} - The preceding item is matched at least n, "
                                 "but at most m times.
"
                                 "
Furthermore, backreferences to bracketed subexpressions are available "
                                 "via the notation \\#.
"
                                 "
See the grep(1) documentation for the full documentation.
"
                                ));
  lblFiles->setWhatsThis(    i18n("Enter the file name pattern of the files to search here.\n"
                                  "You may give several patterns separated by commas."));
  lblFolder->setWhatsThis(    i18n("Enter the folder which contains the files in which you want to search."));
  chkRecursive->setWhatsThis(    i18n("Check this box to search in all subfolders."));
  chkCaseSensitive->setWhatsThis(    i18n("If this option is enabled (the default), the search will be case sensitive."));
  chkFollowSymlinks->setWhatsThis(    i18n("If this option is enabled, the search will follow symlinks to directories. This can lead to infinite recursion if cyclical symlinks exist."));

  connect( this, SIGNAL(user1Clicked()),
           SLOT(slotSearch()) );
  connect( cmbPattern->lineEdit(), SIGNAL(textChanged ( const QString & )),
           SLOT( patternTextChanged( const QString & )));
  connect( btnSync, SIGNAL(clicked()), this, SLOT(syncDir()));

  patternTextChanged( cmbPattern->lineEdit()->text());

  resize(500, 350);
}

KateFindDialog::~KateFindDialog()
{
}

void KateFindDialog::patternTextChanged( const QString & text)
{
  enableButton(User1, !text.isEmpty());
}

void KateFindDialog::slotSearch()
{
  // no pattern set...
  if ( cmbPattern->currentText().isEmpty() )
  {
    cmbPattern->setFocus();
    return;
  }

  // dir does not exist...
  if ( cmbDir->url().isEmpty() || ! QDir(cmbDir->url().toLocalFile ()).exists() )
  {
    cmbDir->setFocus();
    KMessageBox::information( this, i18n(
                                "You must enter an existing local folder in the 'Folder' entry."),
                              i18n("Invalid Folder"), "Kate grep tool: invalid folder" );
    return;
  }

  // regexps
  QRegExp reg (cmbPattern->currentText(), chkCaseSensitive->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive);
  QList<QRegExp> liste;
  liste << reg;

  KateResultView* view = m_view->toolViewFromId(m_useId);
  if (!view) {
    view = new KateResultView(m_mw, m_view);
    m_view->addResultView(view);
  }
  updateConfig();
  view->makeVisible();
  view->startSearch(KateFindInFilesOptions::self(), liste,
                    cmbDir->url().toLocalFile(), cmbFilter->currentText());

  hide();
}

void KateFindDialog::updateConfig()
{
  // update last pattern
  KateFindInFilesOptions::self().addSearchItem(cmbPattern->currentText());
  KateFindInFilesOptions::self().addSearchPath(cmbDir->url().url());
  KateFindInFilesOptions::self().addSearchFilter(cmbFilter->currentText());

  KateFindInFilesOptions::self().setRecursive(chkRecursive->isChecked());
  KateFindInFilesOptions::self().setCaseSensitive(chkCaseSensitive->isChecked());
  KateFindInFilesOptions::self().setRegExp(chkRegExp->isChecked());
  KateFindInFilesOptions::self().setFollowDirectorySymlinks(chkFollowSymlinks->isChecked());
}

void KateFindDialog::updateItems()
{
  cmbPattern->clear();
  cmbDir->clear();
  cmbFilter->clear();

  cmbPattern->insertItems(0, KateFindInFilesOptions::self().searchItems());
  cmbDir->comboBox()->insertItems(0, KateFindInFilesOptions::self().searchPaths());
  cmbFilter->insertItems(0, KateFindInFilesOptions::self().searchFilters());

  cmbPattern->setCurrentIndex(0);
  cmbDir->comboBox()->setCurrentIndex(0);
  cmbFilter->setCurrentIndex(0);

  chkRecursive->setChecked(KateFindInFilesOptions::self().recursive());
  chkCaseSensitive->setChecked(KateFindInFilesOptions::self().caseSensitive());
  chkRegExp->setChecked(KateFindInFilesOptions::self().regExp());
  chkFollowSymlinks->setChecked(KateFindInFilesOptions::self().followDirectorySymlinks());
}

void KateFindDialog::setPattern(const QList<QRegExp>& pattern)
{
  if (pattern.size())
    cmbPattern->setEditText(pattern[0].pattern());
}

void KateFindDialog::setUrl(const QString& url)
{
  cmbDir->setUrl(url);
}

void KateFindDialog::setFilter(const QString& filter)
{
  cmbFilter->setEditText(filter);
}

void KateFindDialog::setOptions(const KateFindInFilesOptions& options)
{
  chkRecursive->setChecked(options.recursive());
  chkCaseSensitive->setChecked(options.caseSensitive());
  chkRegExp->setChecked(options.regExp());
  chkFollowSymlinks->setChecked(options.followDirectorySymlinks());
}

void KateFindDialog::syncDir()
{
  // sync url-requester with active view's path
  KUrl url = m_mw->activeView()->document()->url();
  if (url.isLocalFile())
    cmbDir->setUrl(url.directory());
}

void KateFindDialog::showEvent(QShowEvent* event)
{
  if (event->spontaneous())
    return;

  cmbPattern->setFocus();

  if (!cmbDir->url().isEmpty())
    return;

  syncDir();
}

void KateFindDialog::useResultView(int id)
{
  m_useId = id;
}

#include "katefinddialog.moc"

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>fix regexp option, now actually has some effect<commit_after>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2001, 2004 Anders Lund <anders.lund@lund.tdcadsl.dk>
   Copyright (C) 2007-2008 Dominik Haumann <dhaumann kde org>
   Copyright (C) 2007 Flavio Castelli <flavio.castelli@gmail.com>
   Copyright (C) 2008 Eduardo Robles Elvira <edulix@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "katefinddialog.h"
#include "katefindinfiles.h"
#include "kateresultview.h"
#include "katefindoptions.h"

#include <ktexteditor/document.h>
#include <ktexteditor/view.h>

#include <kdebug.h>

#include <QClipboard>
#include <QRegExp>
#include <QShowEvent>
#include <QLineEdit>

#include <kacceleratormanager.h>
#include <kconfig.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kurlcompletion.h>

KateFindDialog::KateFindDialog(Kate::MainWindow *mw, KateFindInFilesView *view)
    : KDialog(mw->window()), m_mw (mw), m_view(view)
    , m_useId(-1)
{
  setCaption(i18n("Find in Files"));
  setButtons(Close | User1);

  setButtonGuiItem(User1, KStandardGuiItem::find());
  setDefaultButton(User1);

  QWidget* widget = new QWidget(this);
  setupUi(widget);
  setMainWidget(widget);

  // if possible, ui properties are set in the .ui-file

  // set sync icon
  btnSync->setIcon(KIcon("view-refresh"));

  // get url-requester's combo box and sanely initialize
  KComboBox* cmbUrl = cmbDir->comboBox();
  cmbUrl->setDuplicatesEnabled(false);
  cmbUrl->setEditable(true);
  cmbDir->setMode( KFile::Directory | KFile::LocalOnly );
  KUrlCompletion* cmpl = new KUrlCompletion(KUrlCompletion::DirCompletion);
  cmbUrl->setCompletionObject( cmpl );
  cmbUrl->setAutoDeleteCompletionObject( true );

  updateItems();
  syncDir();

  // auto-accels
  KAcceleratorManager::manage( this );

  lblPattern->setWhatsThis( i18n("
Enter the expression you want to search for here.
"
                                 "
If 'regular expression' is unchecked, any non-space letters in your "
                                 "expression will be escaped with a backslash character.
"
                                 "
Possible meta characters are:
"
                                 ". - Matches any character
"
                                 "^ - Matches the beginning of a line
"
                                 "$ - Matches the end of a line
"
                                 "\\< - Matches the beginning of a word
"
                                 "\\> - Matches the end of a word
"
                                 "
The following repetition operators exist:
"
                                 "? - The preceding item is matched at most once
"
                                 "* - The preceding item is matched zero or more times
"
                                 "+ - The preceding item is matched one or more times
"
                                 "{n} - The preceding item is matched exactly n times
"
                                 "{n,} - The preceding item is matched n or more times
"
                                 "{,n} - The preceding item is matched at most n times
"
                                 "{n,m} - The preceding item is matched at least n, "
                                 "but at most m times.
"
                                 "
Furthermore, backreferences to bracketed subexpressions are available "
                                 "via the notation \\#.
"
                                 "
See the grep(1) documentation for the full documentation.
"
                                ));
  lblFiles->setWhatsThis(    i18n("Enter the file name pattern of the files to search here.\n"
                                  "You may give several patterns separated by commas."));
  lblFolder->setWhatsThis(    i18n("Enter the folder which contains the files in which you want to search."));
  chkRecursive->setWhatsThis(    i18n("Check this box to search in all subfolders."));
  chkCaseSensitive->setWhatsThis(    i18n("If this option is enabled (the default), the search will be case sensitive."));
  chkFollowSymlinks->setWhatsThis(    i18n("If this option is enabled, the search will follow symlinks to directories. This can lead to infinite recursion if cyclical symlinks exist."));

  connect( this, SIGNAL(user1Clicked()),
           SLOT(slotSearch()) );
  connect( cmbPattern->lineEdit(), SIGNAL(textChanged ( const QString & )),
           SLOT( patternTextChanged( const QString & )));
  connect( btnSync, SIGNAL(clicked()), this, SLOT(syncDir()));

  patternTextChanged( cmbPattern->lineEdit()->text());

  resize(500, 350);
}

KateFindDialog::~KateFindDialog()
{
}

void KateFindDialog::patternTextChanged( const QString & text)
{
  enableButton(User1, !text.isEmpty());
}

void KateFindDialog::slotSearch()
{
  // no pattern set...
  if ( cmbPattern->currentText().isEmpty() )
  {
    cmbPattern->setFocus();
    return;
  }

  // dir does not exist...
  if ( cmbDir->url().isEmpty() || ! QDir(cmbDir->url().toLocalFile ()).exists() )
  {
    cmbDir->setFocus();
    KMessageBox::information( this, i18n(
                                "You must enter an existing local folder in the 'Folder' entry."),
                              i18n("Invalid Folder"), "Kate grep tool: invalid folder" );
    return;
  }

  // regexps
  QRegExp reg (cmbPattern->currentText()
    , chkCaseSensitive->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive
    , chkRegExp->isChecked() ? QRegExp::RegExp : QRegExp::FixedString);

  QList<QRegExp> liste;
  liste << reg;

  KateResultView* view = m_view->toolViewFromId(m_useId);
  if (!view) {
    view = new KateResultView(m_mw, m_view);
    m_view->addResultView(view);
  }
  updateConfig();
  view->makeVisible();
  view->startSearch(KateFindInFilesOptions::self(), liste,
                    cmbDir->url().toLocalFile(), cmbFilter->currentText());

  hide();
}

void KateFindDialog::updateConfig()
{
  // update last pattern
  KateFindInFilesOptions::self().addSearchItem(cmbPattern->currentText());
  KateFindInFilesOptions::self().addSearchPath(cmbDir->url().url());
  KateFindInFilesOptions::self().addSearchFilter(cmbFilter->currentText());

  KateFindInFilesOptions::self().setRecursive(chkRecursive->isChecked());
  KateFindInFilesOptions::self().setCaseSensitive(chkCaseSensitive->isChecked());
  KateFindInFilesOptions::self().setRegExp(chkRegExp->isChecked());
  KateFindInFilesOptions::self().setFollowDirectorySymlinks(chkFollowSymlinks->isChecked());
}

void KateFindDialog::updateItems()
{
  cmbPattern->clear();
  cmbDir->clear();
  cmbFilter->clear();

  cmbPattern->insertItems(0, KateFindInFilesOptions::self().searchItems());
  cmbDir->comboBox()->insertItems(0, KateFindInFilesOptions::self().searchPaths());
  cmbFilter->insertItems(0, KateFindInFilesOptions::self().searchFilters());

  cmbPattern->setCurrentIndex(0);
  cmbDir->comboBox()->setCurrentIndex(0);
  cmbFilter->setCurrentIndex(0);

  chkRecursive->setChecked(KateFindInFilesOptions::self().recursive());
  chkCaseSensitive->setChecked(KateFindInFilesOptions::self().caseSensitive());
  chkRegExp->setChecked(KateFindInFilesOptions::self().regExp());
  chkFollowSymlinks->setChecked(KateFindInFilesOptions::self().followDirectorySymlinks());
}

void KateFindDialog::setPattern(const QList<QRegExp>& pattern)
{
  if (pattern.size())
    cmbPattern->setEditText(pattern[0].pattern());
}

void KateFindDialog::setUrl(const QString& url)
{
  cmbDir->setUrl(url);
}

void KateFindDialog::setFilter(const QString& filter)
{
  cmbFilter->setEditText(filter);
}

void KateFindDialog::setOptions(const KateFindInFilesOptions& options)
{
  chkRecursive->setChecked(options.recursive());
  chkCaseSensitive->setChecked(options.caseSensitive());
  chkRegExp->setChecked(options.regExp());
  chkFollowSymlinks->setChecked(options.followDirectorySymlinks());
}

void KateFindDialog::syncDir()
{
  // sync url-requester with active view's path
  KUrl url = m_mw->activeView()->document()->url();
  if (url.isLocalFile())
    cmbDir->setUrl(url.directory());
}

void KateFindDialog::showEvent(QShowEvent* event)
{
  if (event->spontaneous())
    return;

  cmbPattern->setFocus();

  if (!cmbDir->url().isEmpty())
    return;

  syncDir();
}

void KateFindDialog::useResultView(int id)
{
  m_useId = id;
}

#include "katefinddialog.moc"

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>/*
 * perspective.cpp
 *
 *  Created on: 2016年12月23日
 *      Author: zhuqian
 */
#include "raiden.h"
#include "perspective.h"
#include "sampling.h"
#include "paramset.h"
#include "film.h"
PerspectiveCamera::PerspectiveCamera(const Transform& c2w,
		const Bound2f& screenWindow, Float shutterOpen, Float shutterEnd,
		Float lensr, Float focald, Float fov,Film * f, const Medium* medium) :
		ProjectiveCamera(c2w, Perspective(fov, 1e-3f, 1000.0f)/*c2s*/,
				screenWindow, shutterOpen, shutterEnd, lensr, focald,f,medium) {
	//获得光栅化空间下，相机空间对应的差分
	_dxCamera = _rasterToCamera(Vector3f(1, 0, 0))
			- _rasterToCamera(Vector3f(0, 0, 0));
	_dyCamera = _rasterToCamera(Vector3f(0, 1, 0))
			- _rasterToCamera(Vector3f(0, 0, 0));
}

Float PerspectiveCamera::GenerateRay(const CameraSample &sample,
		Ray *ray) const {
	Point3f pRas = Point3f(sample.pFilm.x, sample.pFilm.y, 0.0f);
	Point3f pCam = _rasterToCamera(pRas); //计算相机空间下的image panel样本值
	*ray = Ray(Point3f(0,0,0), Normalize(Vector3f(pCam)));
	if (_lensRadius > 0.0f) {
		Point2f lens = ConcentricSampleDisk(sample.pLen) * _lensRadius; //采样Lens
		//计算焦距平面交点
		//其实这的z就是1
		Float ft = _focalDistance / ray->d.z;
		Point3f pFocus = (*ray)(ft);
		//原点设置成来自镜面
		ray->o = Point3f(lens.x, lens.y, 0);
		ray->d = Normalize(pFocus - ray->o);
	}

	ray->time = Lerp(sample.time, shutterOpen, shutterEnd);
	Info(medium);
	ray->medium = medium;
	*ray = cameraToWorld(*ray);
	return 1.0f;
}
Float PerspectiveCamera::GenerateRayDifferential(const CameraSample &sample,
		RayDifferential *ray) const {
	Point3f pRas = Point3f(sample.pFilm.x, sample.pFilm.y, 0.0f);
	Point3f pCam = _rasterToCamera(pRas); //计算相机空间下的image panel样本值
	*ray = RayDifferential(Point3f(0,0,0), Normalize(Vector3f(pCam)));
	if (_lensRadius > 0.0f) {
		Point2f lens = ConcentricSampleDisk(sample.pLen) * _lensRadius; //采样Lens
		//计算焦距平面交点
		//其实这的z就是1
		Float ft = _focalDistance / ray->d.z;
		Point3f pFocus = (*ray)(ft);
		//原点设置成来自镜面
		ray->o = Point3f(lens.x, lens.y, 0);
		ray->d = Normalize(pFocus - ray->o);
	}
	//处理微分信息
	if (_lensRadius > 0.0f) {
		Point2f lens = ConcentricSampleDisk(sample.pLen) * _lensRadius; //采样Lens
		//计算x射线
		Vector3f dx = Normalize(Vector3f(pCam) + _dxCamera);
		Float ft = _focalDistance / dx.z;
		Point3f pFocusX = Point3f(0, 0, 0) + (ft * dx);
		ray->ox = Point3f(lens.x, lens.y, 0);
		ray->dx = Normalize(pFocusX - ray->ox);
		//计算y射线
		Vector3f dy = Normalize(Vector3f(pCam) + _dyCamera);
		ft = _focalDistance / dy.z;
		Point3f pFocusY = Point3f(0, 0, 0) + (ft * dy);
		ray->oy = Point3f(lens.x, lens.y, 0);
		ray->dy = Normalize(pFocusY - ray->oy);
	} else {
		//镜片为奇点的情况
		ray->ox=ray->oy=ray->o;
		ray->dx = Normalize(Vector3f(pCam)+_dxCamera);
		ray->dy = Normalize(Vector3f(pCam)+_dyCamera);
	}
	ray->hasDifferential = true;
	ray->time = Lerp(sample.time, shutterOpen, shutterEnd);
	ray->medium = medium;
	*ray = cameraToWorld(*ray);
	return 1.0;
}

PerspectiveCamera *CreatePerspectiveCamera(const ParamSet &params,
                                           const Transform &cam2world,
                                           Film *film, const Medium *medium) {
    // Extract common camera parameters from _ParamSet_
    Float shutteropen = params.FindOneFloat("shutteropen", 0.f);
    Float shutterclose = params.FindOneFloat("shutterclose", 1.f);
    if (shutterclose < shutteropen) {
        std::swap(shutterclose, shutteropen);
    }
    Float lensradius = params.FindOneFloat("lensradius", 0.f);
    Float focaldistance = params.FindOneFloat("focaldistance", 1e6);
    Float frame = params.FindOneFloat("frameaspectratio",Float(film->fullResolution.x) / Float(film->fullResolution.y));
    Bound2f screen;
    if (frame > 1.f) {
    		screen.minPoint.x = -frame;
    		screen.maxPoint.x = frame;
    		screen.minPoint.y = -1.0f;
    		screen.maxPoint.y = 1.0f;
    	} else {
    		screen.minPoint.x = -1.0f;
    		screen.maxPoint.x = 1.0f;
    		screen.minPoint.y = -1.0f / frame;
    		screen.maxPoint.y = 1.0f / frame;
    	}
    int swi;
    const Float *sw = params.FindFloat("screenwindow", &swi);
    if (sw) {
    		if (swi == 4) {
    			screen.minPoint.x = sw[0];
    			screen.maxPoint.x = sw[1];
    			screen.minPoint.y = sw[2];
    			screen.maxPoint.y = sw[3];
    		} else
    			Error("\"screenwindow\" should have four values");
    	}
    Float fov = params.FindOneFloat("fov", 90.0);
    Float halffov = params.FindOneFloat("halffov", -1.0f);
    if (halffov > 0.0f){
        fov = 2.0f * halffov;
    }
    return new PerspectiveCamera(cam2world, screen, shutteropen, shutterclose,
                                 lensradius, focaldistance, fov,film, medium);
}
<commit_msg>修正错把空间点当成向量来操作，导致差分计算有误的BUG<commit_after>/*
 * perspective.cpp
 *
 *  Created on: 2016年12月23日
 *      Author: zhuqian
 */
#include "raiden.h"
#include "perspective.h"
#include "sampling.h"
#include "paramset.h"
#include "film.h"
PerspectiveCamera::PerspectiveCamera(const Transform& c2w,
		const Bound2f& screenWindow, Float shutterOpen, Float shutterEnd,
		Float lensr, Float focald, Float fov,Film * f, const Medium* medium) :
		ProjectiveCamera(c2w, Perspective(fov, 1e-3f, 1000.0f)/*c2s*/,
				screenWindow, shutterOpen, shutterEnd, lensr, focald,f,medium) {
	//获得光栅化空间下，相机空间对应的差分
	_dxCamera = _rasterToCamera(Point3f(1, 0, 0))
			- _rasterToCamera(Point3f(0, 0, 0));
	_dyCamera = _rasterToCamera(Point3f(0, 1, 0))
			- _rasterToCamera(Point3f(0, 0, 0));
}

Float PerspectiveCamera::GenerateRay(const CameraSample &sample,
		Ray *ray) const {
	Point3f pRas = Point3f(sample.pFilm.x, sample.pFilm.y, 0.0f);
	Point3f pCam = _rasterToCamera(pRas); //计算相机空间下的image panel样本值
	*ray = Ray(Point3f(0,0,0), Normalize(Vector3f(pCam)));
	if (_lensRadius > 0.0f) {
		Point2f lens = ConcentricSampleDisk(sample.pLen) * _lensRadius; //采样Lens
		//计算焦距平面交点
		//其实这的z就是1
		Float ft = _focalDistance / ray->d.z;
		Point3f pFocus = (*ray)(ft);
		//原点设置成来自镜面
		ray->o = Point3f(lens.x, lens.y, 0);
		ray->d = Normalize(pFocus - ray->o);
	}

	ray->time = Lerp(sample.time, shutterOpen, shutterEnd);
	Info(medium);
	ray->medium = medium;
	*ray = cameraToWorld(*ray);
	return 1.0f;
}
Float PerspectiveCamera::GenerateRayDifferential(const CameraSample &sample,
		RayDifferential *ray) const {

	Point3f pRas = Point3f(sample.pFilm.x, sample.pFilm.y, 0.0f);
	Point3f pCam = _rasterToCamera(pRas); //计算相机空间下的image panel样本值

	*ray = RayDifferential(Point3f(0,0,0), Normalize(Vector3f(pCam)));
	if (_lensRadius > 0.0f) {
		Point2f lens = ConcentricSampleDisk(sample.pLen) * _lensRadius; //采样Lens
		//计算焦距平面交点
		//其实这的z就是1
		Float ft = _focalDistance / ray->d.z;
		Point3f pFocus = (*ray)(ft);
		//原点设置成来自镜面
		ray->o = Point3f(lens.x, lens.y, 0);
		ray->d = Normalize(pFocus - ray->o);
	}
	//处理微分信息
	if (_lensRadius > 0.0f) {
		Point2f lens = ConcentricSampleDisk(sample.pLen) * _lensRadius; //采样Lens
		//计算x射线
		Vector3f dx = Normalize(Vector3f(pCam) + _dxCamera);
		Float ft = _focalDistance / dx.z;
		Point3f pFocusX = Point3f(0, 0, 0) + (ft * dx);
		ray->ox = Point3f(lens.x, lens.y, 0);
		ray->dx = Normalize(pFocusX - ray->ox);
		//计算y射线
		Vector3f dy = Normalize(Vector3f(pCam) + _dyCamera);
		ft = _focalDistance / dy.z;
		Point3f pFocusY = Point3f(0, 0, 0) + (ft * dy);
		ray->oy = Point3f(lens.x, lens.y, 0);
		ray->dy = Normalize(pFocusY - ray->oy);
	} else {
		//镜片为奇点的情况
		ray->ox=ray->oy=ray->o;
		ray->dx = Normalize(Vector3f(pCam)+_dxCamera);
		ray->dy = Normalize(Vector3f(pCam)+_dyCamera);
	}
	ray->hasDifferential = true;
	ray->time = Lerp(sample.time, shutterOpen, shutterEnd);
	ray->medium = medium;
	*ray = cameraToWorld(*ray);
	return 1.0;
}

PerspectiveCamera *CreatePerspectiveCamera(const ParamSet &params,
                                           const Transform &cam2world,
                                           Film *film, const Medium *medium) {
    // Extract common camera parameters from _ParamSet_
    Float shutteropen = params.FindOneFloat("shutteropen", 0.f);
    Float shutterclose = params.FindOneFloat("shutterclose", 1.f);
    if (shutterclose < shutteropen) {
        std::swap(shutterclose, shutteropen);
    }
    Float lensradius = params.FindOneFloat("lensradius", 0.f);
    Float focaldistance = params.FindOneFloat("focaldistance", 1e6);
    Float frame = params.FindOneFloat("frameaspectratio",Float(film->fullResolution.x) / Float(film->fullResolution.y));
    Bound2f screen;
    if (frame > 1.f) {
    		screen.minPoint.x = -frame;
    		screen.maxPoint.x = frame;
    		screen.minPoint.y = -1.0f;
    		screen.maxPoint.y = 1.0f;
    	} else {
    		screen.minPoint.x = -1.0f;
    		screen.maxPoint.x = 1.0f;
    		screen.minPoint.y = -1.0f / frame;
    		screen.maxPoint.y = 1.0f / frame;
    	}
    int swi;
    const Float *sw = params.FindFloat("screenwindow", &swi);
    if (sw) {
    		if (swi == 4) {
    			screen.minPoint.x = sw[0];
    			screen.maxPoint.x = sw[1];
    			screen.minPoint.y = sw[2];
    			screen.maxPoint.y = sw[3];
    		} else
    			Error("\"screenwindow\" should have four values");
    	}
    Float fov = params.FindOneFloat("fov", 90.0);
    Float halffov = params.FindOneFloat("halffov", -1.0f);
    if (halffov > 0.0f){
        fov = 2.0f * halffov;
    }
    return new PerspectiveCamera(cam2world, screen, shutteropen, shutterclose,
                                 lensradius, focaldistance, fov,film, medium);
}
<|endoftext|>


<commit_before><commit_msg>fix travis<commit_after>float sum(float a, float b) {
    return a+b;
}
<|endoftext|>


<commit_before>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2014, Cauldron Development LLC
                 Copyright (c) 2003-2014, Stanford University
                             All rights reserved.

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

        The C! library is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        Lesser General Public License for more details.

        You should have received a copy of the GNU Lesser General Public
        License along with the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#include "JSONAPI.h"

#include <cbang/String.h>
#include <cbang/log/Logger.h>
#include <cbang/json/JSON.h>
#include <cbang/json/List.h>
#include <cbang/http/WebContext.h>
#include <cbang/http/Connection.h>
#include <cbang/http/StatusCode.h>

using namespace cb;
using namespace cb::JSAPI;
using namespace std;

void JSONAPI::add(const string &cmd, const SmartPointer<Handler> &handler) {
  if (!api.insert(api_t::value_type(cmd, handler)).second)
    THROWS("'" << root << cmd << "' already exists in JSON API");
}

bool JSONAPI::handlePage(HTTP::WebContext &ctx, ostream &stream,
                         const URI &uri) {
  if (!String::startsWith(uri.getPath(), root)) return false;

  string cmd = uri.getPath().substr(root.length());

  // Look up command
  api_t::const_iterator it = api.find(cmd);
  if (it == api.end()) return false;

  ctx.setDynamic(); // Don't cache
  HTTP::Connection &con = ctx.getConnection();

  bool jsonp = !jsonpCB.empty() && uri.has(jsonpCB);

  if (jsonp) {
    con.getResponse().setContentType("application/javascript");
    con << uri.get(jsonpCB) << '(';

  } else con.getResponse().setContentType("application/json");

  JSON::Writer writer(con, 0, !uri.has("pretty"),
                      uri.has("python_mode") ? JSON::Writer::PYTHON_MODE :
                      JSON::Writer::JSON_MODE);

  try {
    // Parse JSON data
    JSON::ValuePtr msg;
    if (con.getRequest().hasContentType() &&
        String::startsWith(con.getRequest().getContentType(),
                           "application/json")) {
      MemoryBuffer &payload = con.getPayload();
      if (payload.getFill()) msg = JSON::Reader(payload).parse();

    } else if (!uri.empty()) {
      msg = new JSON::Dict;

      for (URI::const_iterator it = uri.begin(); it != uri.end(); it++)
        msg->insert(it->first, it->second);
    }

    // Dispatch API command
    if (msg.isNull()) LOG_DEBUG(5, "JSONAPI Call: " << cmd << "()");
    else LOG_DEBUG(5, "JSONAPI Call: " << cmd << '(' << *msg << ')');
    it->second->handle(ctx, cmd, msg, writer);

    // Make sure JSON stream is complete
    writer.close();

  } catch (const Exception &e) {
    LOG_DEBUG(5, e);

    // Clear possibly partial or invalid response
    con.clearResponseBuffer();

    // jsonp header
    if (jsonp) con << uri.get(jsonpCB) << '(';

    // Send error message
    JSON::Writer writer(con, 0, true);
    writer.beginList();
    writer.append("error");
    writer.append(e.getMessage());
    writer.endList();
    writer.close();
  }

  if (jsonp) con << ");";

  return true;
}
<commit_msg>Print full error in JSON API<commit_after>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2014, Cauldron Development LLC
                 Copyright (c) 2003-2014, Stanford University
                             All rights reserved.

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

        The C! library is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        Lesser General Public License for more details.

        You should have received a copy of the GNU Lesser General Public
        License along with the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#include "JSONAPI.h"

#include <cbang/String.h>
#include <cbang/log/Logger.h>
#include <cbang/json/JSON.h>
#include <cbang/json/List.h>
#include <cbang/http/WebContext.h>
#include <cbang/http/Connection.h>
#include <cbang/http/StatusCode.h>

using namespace cb;
using namespace cb::JSAPI;
using namespace std;

void JSONAPI::add(const string &cmd, const SmartPointer<Handler> &handler) {
  if (!api.insert(api_t::value_type(cmd, handler)).second)
    THROWS("'" << root << cmd << "' already exists in JSON API");
}

bool JSONAPI::handlePage(HTTP::WebContext &ctx, ostream &stream,
                         const URI &uri) {
  if (!String::startsWith(uri.getPath(), root)) return false;

  string cmd = uri.getPath().substr(root.length());

  // Look up command
  api_t::const_iterator it = api.find(cmd);
  if (it == api.end()) return false;

  ctx.setDynamic(); // Don't cache
  HTTP::Connection &con = ctx.getConnection();

  bool jsonp = !jsonpCB.empty() && uri.has(jsonpCB);

  if (jsonp) {
    con.getResponse().setContentType("application/javascript");
    con << uri.get(jsonpCB) << '(';

  } else con.getResponse().setContentType("application/json");

  JSON::Writer writer(con, 0, !uri.has("pretty"),
                      uri.has("python_mode") ? JSON::Writer::PYTHON_MODE :
                      JSON::Writer::JSON_MODE);

  try {
    // Parse JSON data
    JSON::ValuePtr msg;
    if (con.getRequest().hasContentType() &&
        String::startsWith(con.getRequest().getContentType(),
                           "application/json")) {
      MemoryBuffer &payload = con.getPayload();
      if (payload.getFill()) msg = JSON::Reader(payload).parse();

    } else if (!uri.empty()) {
      msg = new JSON::Dict;

      for (URI::const_iterator it = uri.begin(); it != uri.end(); it++)
        msg->insert(it->first, it->second);
    }

    // Dispatch API command
    if (msg.isNull()) LOG_DEBUG(5, "JSONAPI Call: " << cmd << "()");
    else LOG_DEBUG(5, "JSONAPI Call: " << cmd << '(' << *msg << ')');
    it->second->handle(ctx, cmd, msg, writer);

    // Make sure JSON stream is complete
    writer.close();

  } catch (const Exception &e) {
    LOG_ERROR(e);

    // Clear possibly partial or invalid response
    con.clearResponseBuffer();

    // jsonp header
    if (jsonp) con << uri.get(jsonpCB) << '(';

    // Send error message
    JSON::Writer writer(con, 0, true);
    writer.beginList();
    writer.append("error");
    writer.append(e.getMessage());
    writer.endList();
    writer.close();
  }

  if (jsonp) con << ");";

  return true;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  imgui-d3d11.cc
//  Dear ImGui integration sample with D3D11 backend.
//------------------------------------------------------------------------------
#include "d3d11entry.h"
#define SOKOL_IMPL
#define SOKOL_D3D11
#define SOKOL_D3D11_SHADER_COMPILER
#define SOKOL_LOG(s) OutputDebugStringA(s)
#include "sokol_gfx.h"
#include "sokol_time.h"
#include "imgui.h"

static const int Width = 1024;
static const int Height = 768;
static const int MaxVertices = (1<<16);
static const int MaxIndices = MaxVertices * 3;

static uint64_t last_time = 0;
static bool show_test_window = true;
static bool show_another_window = false;

static sg_pipeline pip;
static sg_bindings bind;
static sg_pass_action pass_action;

typedef struct {
    ImVec2 disp_size;
} vs_params_t;

static void imgui_draw_cb(ImDrawData*);

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
    // setup d3d11 app wrapper, sokol_gfx, sokol_time
    d3d11_init(Width, Height, 1, L"Sokol Dear ImGui D3D11");
    sg_desc desc = { };
    desc.d3d11_device = d3d11_device();
    desc.d3d11_device_context = d3d11_device_context();
    desc.d3d11_render_target_view_cb = d3d11_render_target_view;
    desc.d3d11_depth_stencil_view_cb = d3d11_depth_stencil_view;
    sg_setup(&desc);
    stm_setup();

    // input forwarding
    d3d11_mouse_pos([] (float x, float y)   { ImGui::GetIO().MousePos = ImVec2(x, y); });
    d3d11_mouse_btn_down([] (int btn)       { ImGui::GetIO().MouseDown[btn] = true; });
    d3d11_mouse_btn_up([] (int btn)         { ImGui::GetIO().MouseDown[btn] = false; });
    d3d11_mouse_wheel([](float v)           { ImGui::GetIO().MouseWheel = v; });
    d3d11_char([] (wchar_t c)               { ImGui::GetIO().AddInputCharacter(c); });
    d3d11_key_down([] (int key)             { if (key < 512) ImGui::GetIO().KeysDown[key] = true; });
    d3d11_key_up([] (int key)               { if (key < 512) ImGui::GetIO().KeysDown[key] = false; });

    // setup Dear Imgui
    ImGui::CreateContext();
    ImGui::StyleColorsDark();
    ImGuiIO& io = ImGui::GetIO();
    io.IniFilename = nullptr;
    io.RenderDrawListsFn = imgui_draw_cb;
    io.Fonts->AddFontDefault();
    io.KeyMap[ImGuiKey_Tab] = VK_TAB;
    io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
    io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
    io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
    io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
    io.KeyMap[ImGuiKey_Home] = VK_HOME;
    io.KeyMap[ImGuiKey_End] = VK_END;
    io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
    io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
    io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
    io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
    io.KeyMap[ImGuiKey_A] = 'A';
    io.KeyMap[ImGuiKey_C] = 'C';
    io.KeyMap[ImGuiKey_V] = 'V';
    io.KeyMap[ImGuiKey_X] = 'X';
    io.KeyMap[ImGuiKey_Y] = 'Y';
    io.KeyMap[ImGuiKey_Z] = 'Z';

    // dynamic vertex- and index-buffers for imgui-generated geometry
    sg_buffer_desc vbuf_desc = { };
    vbuf_desc.usage = SG_USAGE_STREAM;
    vbuf_desc.size = MaxVertices * sizeof(ImDrawVert);
    bind.vertex_buffers[0] = sg_make_buffer(&vbuf_desc);

    sg_buffer_desc ibuf_desc = { };
    ibuf_desc.type = SG_BUFFERTYPE_INDEXBUFFER;
    ibuf_desc.usage = SG_USAGE_STREAM;
    ibuf_desc.size = MaxIndices * sizeof(ImDrawIdx);
    bind.index_buffer = sg_make_buffer(&ibuf_desc);

    // font texture for imgui's default font
    unsigned char* font_pixels;
    int font_width, font_height;
    io.Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height);
    sg_image_desc img_desc = { };
    img_desc.width = font_width;
    img_desc.height = font_height;
    img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
    img_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE;
    img_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE;
    img_desc.content.subimage[0][0].ptr = font_pixels;
    img_desc.content.subimage[0][0].size = font_width * font_height * 4;
    bind.fs_images[0] = sg_make_image(&img_desc);

    // shader object for imgui rendering
    sg_shader_desc shd_desc = { };
    auto& ub = shd_desc.vs.uniform_blocks[0];
    ub.size = sizeof(vs_params_t);
    shd_desc.vs.source =
        "cbuffer params {\n"
        "  float2 disp_size;\n"
        "};\n"
        "struct vs_in {\n"
        "  float2 pos: POSITION;\n"
        "  float2 uv: TEXCOORD0;\n"
        "  float4 color: COLOR0;\n"
        "};\n"
        "struct vs_out {\n"
        "  float2 uv: TEXCOORD0;\n"
        "  float4 color: COLOR0;\n"
        "  float4 pos: SV_Position;\n"
        "};\n"
        "vs_out main(vs_in inp) {\n"
        "  vs_out outp;\n"
        "  outp.pos = float4(((inp.pos/disp_size)-0.5)*float2(2.0,-2.0), 0.5, 1.0);\n"
        "  outp.uv = inp.uv;\n"
        "  outp.color = inp.color;\n"
        "  return outp;\n"
        "}\n";
    shd_desc.fs.images[0].type = SG_IMAGETYPE_2D;
    shd_desc.fs.source =
        "Texture2D<float4> tex: register(t0);\n"
        "sampler smp: register(s0);\n"
        "float4 main(float2 uv: TEXCOORD0, float4 color: COLOR0): SV_Target0 {\n"
        "  return tex.Sample(smp, uv) * color;\n"
        "}\n";
    sg_shader shd = sg_make_shader(&shd_desc);

    // pipeline object for imgui rendering
    sg_pipeline_desc pip_desc = { };
    pip_desc.layout.buffers[0].stride = sizeof(ImDrawVert);
    auto& attrs = pip_desc.layout.attrs;
    attrs[0].sem_name="POSITION"; attrs[0].offset=offsetof(ImDrawVert, pos); attrs[0].format=SG_VERTEXFORMAT_FLOAT2;
    attrs[1].sem_name="TEXCOORD"; attrs[1].offset=offsetof(ImDrawVert, uv); attrs[1].format=SG_VERTEXFORMAT_FLOAT2;
    attrs[2].sem_name="COLOR"; attrs[2].offset=offsetof(ImDrawVert, col); attrs[2].format=SG_VERTEXFORMAT_UBYTE4N;
    pip_desc.shader = shd;
    pip_desc.index_type = SG_INDEXTYPE_UINT16;
    pip_desc.blend.enabled = true;
    pip_desc.blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA;
    pip_desc.blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
    pip_desc.blend.color_write_mask = SG_COLORMASK_RGB;
    pip = sg_make_pipeline(&pip_desc);

    // initial clear color
    pass_action.colors[0].action = SG_ACTION_CLEAR;
    pass_action.colors[0].val[0] = 0.0f;
    pass_action.colors[0].val[1] = 0.5f;
    pass_action.colors[0].val[2] = 0.7f;
    pass_action.colors[0].val[3] = 1.0f;

    // draw loop
    while (d3d11_process_events()) {
        const int cur_width = d3d11_width();
        const int cur_height = d3d11_height();

        // this is standard ImGui demo code
        ImGuiIO& io = ImGui::GetIO();
        io.DisplaySize = ImVec2(float(cur_width), float(cur_height));
        io.DeltaTime = (float) stm_sec(stm_laptime(&last_time));
        ImGui::NewFrame();

        // 1. Show a simple window
        // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
        static float f = 0.0f;
        ImGui::Text("Hello, world!");
        ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
        ImGui::ColorEdit3("clear color", &pass_action.colors[0].val[0]);
        if (ImGui::Button("Test Window")) show_test_window ^= 1;
        if (ImGui::Button("Another Window")) show_another_window ^= 1;
        ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

        // 2. Show another simple window, this time using an explicit Begin/End pair
        if (show_another_window) {
            ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
            ImGui::Begin("Another Window", &show_another_window);
            ImGui::Text("Hello");
            ImGui::End();
        }

        // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
        if (show_test_window) {
            ImGui::SetNextWindowPos(ImVec2(460, 20), ImGuiSetCond_FirstUseEver);
            ImGui::ShowTestWindow();
        }

        // the sokol_gfx draw pass
        sg_begin_default_pass(&pass_action, cur_width, cur_height);
        ImGui::Render();
        sg_end_pass();
        sg_commit();
        d3d11_present();
    }
    ImGui::DestroyContext();
    sg_shutdown();
    d3d11_shutdown();
}

// imgui draw callback
void imgui_draw_cb(ImDrawData* draw_data) {
    assert(draw_data);
    if (draw_data->CmdListsCount == 0) {
        return;
    }

    // render the command list
    vs_params_t vs_params;
    vs_params.disp_size.x = ImGui::GetIO().DisplaySize.x;
    vs_params.disp_size.y = ImGui::GetIO().DisplaySize.y;
    sg_apply_pipeline(pip);
    sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
    for (int cl_index = 0; cl_index < draw_data->CmdListsCount; cl_index++) {
        const ImDrawList* cl = draw_data->CmdLists[cl_index];

        // append vertices and indices to buffers, record start offsets in bindings struct
        const int vtx_size = cl->VtxBuffer.size() * sizeof(ImDrawVert);
        const int idx_size = cl->IdxBuffer.size() * sizeof(ImDrawIdx);
        const int vb_offset = sg_append_buffer(bind.vertex_buffers[0], &cl->VtxBuffer.front(), vtx_size);
        const int ib_offset = sg_append_buffer(bind.index_buffer, &cl->IdxBuffer.front(), idx_size);
        /* don't render anything if the buffer is in overflow state (this is also
            checked internally in sokol_gfx, draw calls that attempt from
            overflowed buffers will be silently dropped)
        */
        if (sg_query_buffer_overflow(bind.vertex_buffers[0]) ||
            sg_query_buffer_overflow(bind.index_buffer))
        {
            continue;
        }

        bind.vertex_buffer_offsets[0] = vb_offset;
        bind.index_buffer_offset = ib_offset;
        sg_apply_bindings(&bind);

        int base_element = 0;
        for (const ImDrawCmd& pcmd : cl->CmdBuffer) {
            if (pcmd.UserCallback) {
                pcmd.UserCallback(cl, &pcmd);
            }
            else {
                const int scissor_x = (int) (pcmd.ClipRect.x);
                const int scissor_y = (int) (pcmd.ClipRect.y);
                const int scissor_w = (int) (pcmd.ClipRect.z - pcmd.ClipRect.x);
                const int scissor_h = (int) (pcmd.ClipRect.w - pcmd.ClipRect.y);
                sg_apply_scissor_rect(scissor_x, scissor_y, scissor_w, scissor_h, true);
                sg_draw(base_element, pcmd.ElemCount, 1);
            }
            base_element += pcmd.ElemCount;
        }
    }
}
<commit_msg>remove the ImGui draw callback from the D3D11 ImGui sample<commit_after>//------------------------------------------------------------------------------
//  imgui-d3d11.cc
//  Dear ImGui integration sample with D3D11 backend.
//------------------------------------------------------------------------------
#include "d3d11entry.h"
#define SOKOL_IMPL
#define SOKOL_D3D11
#define SOKOL_D3D11_SHADER_COMPILER
#define SOKOL_LOG(s) OutputDebugStringA(s)
#include "sokol_gfx.h"
#include "sokol_time.h"
#include "imgui.h"

static const int Width = 1024;
static const int Height = 768;
static const int MaxVertices = (1<<16);
static const int MaxIndices = MaxVertices * 3;

static uint64_t last_time = 0;
static bool show_test_window = true;
static bool show_another_window = false;

static sg_pipeline pip;
static sg_bindings bind;
static sg_pass_action pass_action;

typedef struct {
    ImVec2 disp_size;
} vs_params_t;

static void draw_imgui(ImDrawData*);

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
    // setup d3d11 app wrapper, sokol_gfx, sokol_time
    d3d11_init(Width, Height, 1, L"Sokol Dear ImGui D3D11");
    sg_desc desc = { };
    desc.d3d11_device = d3d11_device();
    desc.d3d11_device_context = d3d11_device_context();
    desc.d3d11_render_target_view_cb = d3d11_render_target_view;
    desc.d3d11_depth_stencil_view_cb = d3d11_depth_stencil_view;
    sg_setup(&desc);
    stm_setup();

    // input forwarding
    d3d11_mouse_pos([] (float x, float y)   { ImGui::GetIO().MousePos = ImVec2(x, y); });
    d3d11_mouse_btn_down([] (int btn)       { ImGui::GetIO().MouseDown[btn] = true; });
    d3d11_mouse_btn_up([] (int btn)         { ImGui::GetIO().MouseDown[btn] = false; });
    d3d11_mouse_wheel([](float v)           { ImGui::GetIO().MouseWheel = v; });
    d3d11_char([] (wchar_t c)               { ImGui::GetIO().AddInputCharacter(c); });
    d3d11_key_down([] (int key)             { if (key < 512) ImGui::GetIO().KeysDown[key] = true; });
    d3d11_key_up([] (int key)               { if (key < 512) ImGui::GetIO().KeysDown[key] = false; });

    // setup Dear Imgui
    ImGui::CreateContext();
    ImGui::StyleColorsDark();
    ImGuiIO& io = ImGui::GetIO();
    io.IniFilename = nullptr;
    io.Fonts->AddFontDefault();
    io.KeyMap[ImGuiKey_Tab] = VK_TAB;
    io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
    io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
    io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
    io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
    io.KeyMap[ImGuiKey_Home] = VK_HOME;
    io.KeyMap[ImGuiKey_End] = VK_END;
    io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
    io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
    io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
    io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
    io.KeyMap[ImGuiKey_A] = 'A';
    io.KeyMap[ImGuiKey_C] = 'C';
    io.KeyMap[ImGuiKey_V] = 'V';
    io.KeyMap[ImGuiKey_X] = 'X';
    io.KeyMap[ImGuiKey_Y] = 'Y';
    io.KeyMap[ImGuiKey_Z] = 'Z';

    // dynamic vertex- and index-buffers for imgui-generated geometry
    sg_buffer_desc vbuf_desc = { };
    vbuf_desc.usage = SG_USAGE_STREAM;
    vbuf_desc.size = MaxVertices * sizeof(ImDrawVert);
    bind.vertex_buffers[0] = sg_make_buffer(&vbuf_desc);

    sg_buffer_desc ibuf_desc = { };
    ibuf_desc.type = SG_BUFFERTYPE_INDEXBUFFER;
    ibuf_desc.usage = SG_USAGE_STREAM;
    ibuf_desc.size = MaxIndices * sizeof(ImDrawIdx);
    bind.index_buffer = sg_make_buffer(&ibuf_desc);

    // font texture for imgui's default font
    unsigned char* font_pixels;
    int font_width, font_height;
    io.Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height);
    sg_image_desc img_desc = { };
    img_desc.width = font_width;
    img_desc.height = font_height;
    img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
    img_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE;
    img_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE;
    img_desc.content.subimage[0][0].ptr = font_pixels;
    img_desc.content.subimage[0][0].size = font_width * font_height * 4;
    bind.fs_images[0] = sg_make_image(&img_desc);

    // shader object for imgui rendering
    sg_shader_desc shd_desc = { };
    auto& ub = shd_desc.vs.uniform_blocks[0];
    ub.size = sizeof(vs_params_t);
    shd_desc.vs.source =
        "cbuffer params {\n"
        "  float2 disp_size;\n"
        "};\n"
        "struct vs_in {\n"
        "  float2 pos: POSITION;\n"
        "  float2 uv: TEXCOORD0;\n"
        "  float4 color: COLOR0;\n"
        "};\n"
        "struct vs_out {\n"
        "  float2 uv: TEXCOORD0;\n"
        "  float4 color: COLOR0;\n"
        "  float4 pos: SV_Position;\n"
        "};\n"
        "vs_out main(vs_in inp) {\n"
        "  vs_out outp;\n"
        "  outp.pos = float4(((inp.pos/disp_size)-0.5)*float2(2.0,-2.0), 0.5, 1.0);\n"
        "  outp.uv = inp.uv;\n"
        "  outp.color = inp.color;\n"
        "  return outp;\n"
        "}\n";
    shd_desc.fs.images[0].type = SG_IMAGETYPE_2D;
    shd_desc.fs.source =
        "Texture2D<float4> tex: register(t0);\n"
        "sampler smp: register(s0);\n"
        "float4 main(float2 uv: TEXCOORD0, float4 color: COLOR0): SV_Target0 {\n"
        "  return tex.Sample(smp, uv) * color;\n"
        "}\n";
    sg_shader shd = sg_make_shader(&shd_desc);

    // pipeline object for imgui rendering
    sg_pipeline_desc pip_desc = { };
    pip_desc.layout.buffers[0].stride = sizeof(ImDrawVert);
    auto& attrs = pip_desc.layout.attrs;
    attrs[0].sem_name="POSITION"; attrs[0].offset=offsetof(ImDrawVert, pos); attrs[0].format=SG_VERTEXFORMAT_FLOAT2;
    attrs[1].sem_name="TEXCOORD"; attrs[1].offset=offsetof(ImDrawVert, uv); attrs[1].format=SG_VERTEXFORMAT_FLOAT2;
    attrs[2].sem_name="COLOR"; attrs[2].offset=offsetof(ImDrawVert, col); attrs[2].format=SG_VERTEXFORMAT_UBYTE4N;
    pip_desc.shader = shd;
    pip_desc.index_type = SG_INDEXTYPE_UINT16;
    pip_desc.blend.enabled = true;
    pip_desc.blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA;
    pip_desc.blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
    pip_desc.blend.color_write_mask = SG_COLORMASK_RGB;
    pip = sg_make_pipeline(&pip_desc);

    // initial clear color
    pass_action.colors[0].action = SG_ACTION_CLEAR;
    pass_action.colors[0].val[0] = 0.0f;
    pass_action.colors[0].val[1] = 0.5f;
    pass_action.colors[0].val[2] = 0.7f;
    pass_action.colors[0].val[3] = 1.0f;

    // draw loop
    while (d3d11_process_events()) {
        const int cur_width = d3d11_width();
        const int cur_height = d3d11_height();

        // this is standard ImGui demo code
        ImGuiIO& io = ImGui::GetIO();
        io.DisplaySize = ImVec2(float(cur_width), float(cur_height));
        io.DeltaTime = (float) stm_sec(stm_laptime(&last_time));
        ImGui::NewFrame();

        // 1. Show a simple window
        // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
        static float f = 0.0f;
        ImGui::Text("Hello, world!");
        ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
        ImGui::ColorEdit3("clear color", &pass_action.colors[0].val[0]);
        if (ImGui::Button("Test Window")) show_test_window ^= 1;
        if (ImGui::Button("Another Window")) show_another_window ^= 1;
        ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

        // 2. Show another simple window, this time using an explicit Begin/End pair
        if (show_another_window) {
            ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
            ImGui::Begin("Another Window", &show_another_window);
            ImGui::Text("Hello");
            ImGui::End();
        }

        // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
        if (show_test_window) {
            ImGui::SetNextWindowPos(ImVec2(460, 20), ImGuiSetCond_FirstUseEver);
            ImGui::ShowTestWindow();
        }

        // the sokol_gfx draw pass
        sg_begin_default_pass(&pass_action, cur_width, cur_height);
        ImGui::Render();
        draw_imgui(ImGui::GetDrawData());
        sg_end_pass();
        sg_commit();
        d3d11_present();
    }
    ImGui::DestroyContext();
    sg_shutdown();
    d3d11_shutdown();
}

// render ImGui draw lists through sokol-gfx
void draw_imgui(ImDrawData* draw_data) {
    assert(draw_data);
    if (draw_data->CmdListsCount == 0) {
        return;
    }

    // render the command list
    vs_params_t vs_params;
    vs_params.disp_size.x = ImGui::GetIO().DisplaySize.x;
    vs_params.disp_size.y = ImGui::GetIO().DisplaySize.y;
    sg_apply_pipeline(pip);
    sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
    for (int cl_index = 0; cl_index < draw_data->CmdListsCount; cl_index++) {
        const ImDrawList* cl = draw_data->CmdLists[cl_index];

        // append vertices and indices to buffers, record start offsets in bindings struct
        const int vtx_size = cl->VtxBuffer.size() * sizeof(ImDrawVert);
        const int idx_size = cl->IdxBuffer.size() * sizeof(ImDrawIdx);
        const int vb_offset = sg_append_buffer(bind.vertex_buffers[0], &cl->VtxBuffer.front(), vtx_size);
        const int ib_offset = sg_append_buffer(bind.index_buffer, &cl->IdxBuffer.front(), idx_size);
        /* don't render anything if the buffer is in overflow state (this is also
            checked internally in sokol_gfx, draw calls that attempt from
            overflowed buffers will be silently dropped)
        */
        if (sg_query_buffer_overflow(bind.vertex_buffers[0]) ||
            sg_query_buffer_overflow(bind.index_buffer))
        {
            continue;
        }

        bind.vertex_buffer_offsets[0] = vb_offset;
        bind.index_buffer_offset = ib_offset;
        sg_apply_bindings(&bind);

        int base_element = 0;
        for (const ImDrawCmd& pcmd : cl->CmdBuffer) {
            if (pcmd.UserCallback) {
                pcmd.UserCallback(cl, &pcmd);
            }
            else {
                const int scissor_x = (int) (pcmd.ClipRect.x);
                const int scissor_y = (int) (pcmd.ClipRect.y);
                const int scissor_w = (int) (pcmd.ClipRect.z - pcmd.ClipRect.x);
                const int scissor_h = (int) (pcmd.ClipRect.w - pcmd.ClipRect.y);
                sg_apply_scissor_rect(scissor_x, scissor_y, scissor_w, scissor_h, true);
                sg_draw(base_element, pcmd.ElemCount, 1);
            }
            base_element += pcmd.ElemCount;
        }
    }
}
<|endoftext|>


<commit_before>//=====================================================================//
/*! @file
    @brief  RX メイン
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "main.hpp"
#include "rx/rx63x/system.hpp"
#include "rx/rx63x/port.hpp"
#include "rx/rx63x/mpc.hpp"
#include "rx/cmt_io.hpp"
#include "rx/sci_io.hpp"
#include "rx/gpt_io.hpp"
#include "rx/adc_io.hpp"
#include "rx/chout.hpp"
#include "inv_monitor.hpp"

namespace root {
	device::cmt_io<device::CMT0>  cmt_;
	device::sci_io<device::SCI1, 256, 256>  sci_;
	device::gpt_io<device::GPT0>  gpt_;
	device::adc_io<device::S12AD> adc_;
	utils::chout chout_;
	utils::inv_monitor monitor_;
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字出力
	@param[in]	ch	文字コード
 */
//-----------------------------------------------------------------//
void sci_putch(char ch)
{
	root::sci_.putch(ch);
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字列出力
	@param[in]	str	文字列
 */
//-----------------------------------------------------------------//
void sci_puts(const char *str)
{
	root::sci_.puts(str);
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字入力
	@return 文字コード
 */
//-----------------------------------------------------------------//
char sci_getch(void)
{
	return root::sci_.getch();
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字入力数を取得
	@return 入力文字数
 */
//-----------------------------------------------------------------//
uint32_t sci_length(void)
{
	return root::sci_.length();
}

//-----------------------------------------------------------------//
/*!
	@brief	10ms 単位タイマー
 */
//-----------------------------------------------------------------//
void delay_10ms(uint32_t n)
{
	while(n > 0) {
		root::cmt_.sync();
		--n;
	}
}

void prn_voltage_(const char* info, int32_t v)
{
	int32_t vv = v * 15 * 100 / 4096;
	int32_t mod = vv % 100;
	if(mod < 0) mod = -mod;
	root::chout_.suppress_char(' ');
	root::chout_.set_length(0);
	root::chout_ << info << (vv / 100) << '.';
	root::chout_.suppress_char('0');
	root::chout_.set_length(2);
	root::chout_ << mod << utils::chout::endl;
}

void prn_value_(const char* info, int32_t v)
{
	root::chout_.suppress_char(' ');
	root::chout_.set_length(0);
	root::chout_ << info << v << utils::chout::endl;
}

static volatile uint8_t dummy_;

static void wait_()
{
	// とりあえず無駄ループ
	for(uint32_t i = 0; i < 5000; ++i) {
		i += dummy_ & 0;
	}
}
int main(int argc, char** argv);

int main(int argc, char** argv)
{
	using namespace root;

	device::SYSTEM::PRCR = 0xa503;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MOSCWTCR.MSTS = 0b01101;	// 131072 サイクル待ち
	device::SYSTEM::MOSCCR.MOSTP = 0;			// メインクロック発振器動作
	dummy_ = device::SYSTEM::MOSCCR.MOSTP();
	device::SYSTEM::MOFCR.MOFXIN = 1;			// メインクロック強制発振
	dummy_ = device::SYSTEM::MOFCR.MOFXIN();
	wait_();

	device::SYSTEM::PLLCR.STC = 0xf;			// PLL 16 倍(192MHz)
	device::SYSTEM::PLLWTCR.PSTS = 0b01010;		// 131072 サイクル待ち
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	wait_();

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(3)		// 1/8 (192/8=24)
						  | device::SYSTEM::SCKCR.ICK.b(1)		// 1/2 (192/2=96)
						  | device::SYSTEM::SCKCR.BCK.b(2)		// 1/4 (192/4=48)
						  | device::SYSTEM::SCKCR.PCKA.b(1)		// 1/2 (192/2=96)
						  | device::SYSTEM::SCKCR.PCKB.b(2)		// 1/4 (192/4=48)
						  | device::SYSTEM::SCKCR.PCKC.b(2)		// 1/4 (192/8=48)
						  | device::SYSTEM::SCKCR.PCKD.b(2);	// 1/4 (192/8=48)
	device::SYSTEM::SCKCR3.CKSEL = 4;	///< PLL 回路選択

	// Signal LED 出力設定
	device::PORTB::PDR.B7 = 1; // PORTB:B7 output
	device::PORTB::PODR.B7 = 1; // LED Off

	// SCI1 の初期化（PD5:RXD1:input, PD3:TXD1:output）
	device::PORTD::PDR.B3 = 1;
	device::MPC::PWPR.B0WI = 0;				// PWPR 書き込み許可
	device::MPC::PWPR.PFSWE = 1;			// PxxPFS 書き込み許可
	device::MPC::PD3PFS.PSEL = 0b01010;		// TXD1 設定
	device::MPC::PD5PFS.PSEL = 0b01010;		// RXD1 設定
	device::MPC::PWPR = device::MPC::PWPR.B0WI.b();	// MPC 書き込み禁止
	device::PORTD::PMR.B3 = 1;
	device::PORTD::PMR.B5 = 1;
	static const uint8_t sci_irq_level = 1;
	sci_.initialize(sci_irq_level);
	sci_.start(115200);

	// GPT0 設定 (GTIOC0A: P71:38, PD7:12)(GTIOC0B: P74:35, PD6:13)
	device::PORT7::PDR.B1 = 1;			// output
	device::SYSTEM::MSTPCRA.MSTPA7 = 0; // GPT0..3 モジュール有効
	device::MPC::PWPR.B0WI = 0;			// PWPR 書き込み許可
	device::MPC::PWPR.PFSWE = 1;		// PxxPFS 書き込み許可
	device::MPC::P71PFS.PSEL = 0b0110;	// GTIOC0A 設定
	device::MPC::PWPR = device::MPC::PWPR.B0WI.b();	// MPC 書き込み禁止
	device::PORT7::PMR.B1 = 1;
	gpt_.start();	// PWM start
	gpt_.set_r(512 - 1);
	gpt_.set_a(256);

	// S12AD 設定 P40(56), P41(55), P42(54)
	device::SYSTEM::MSTPCRA.MSTPA17 = 0; // S12AD モジュール有効
	device::MPC::PWPR.B0WI = 0;			 // PWPR 書き込み許可
	device::MPC::PWPR.PFSWE = 1;		 // PxxPFS 書き込み許可
	device::MPC::P40PFS.ASEL = 1;	     // アナログ入力設定
	device::MPC::P41PFS.ASEL = 1;	     // アナログ入力設定
	device::MPC::PWPR = device::MPC::PWPR.B0WI.b();	// MPC 書き込み禁止

	// タイマー設定
	cmt_.set_clock(F_PCKB);
	uint8_t cmt_irq_level = 3;
	cmt_.initialize(93750, cmt_irq_level);

	cmt_.sync();

	monitor_.initialize();

///	device::SYSTEM::PRCR = 0xa500;	///< クロック、低消費電力、関係書き込み禁止

	for(int i = 0; i < 10; ++i) {
		adc_.start(0b00000111);
		cmt_.sync();
		adc_.sync();
		int32_t v = static_cast<int32_t>(adc_.get(0));
		prn_value_("Ch0: ", v);
	}

	uint32_t cnt = 0;
	uint32_t led = 0;

	int32_t ds = 0;

	int32_t ref = 300;

	int32_t val = 0;

	int32_t low_limit = 10; // 0.23V at 12V input
	int32_t high_limit = 500; // 11.72V at 12V input
	int32_t cpv = low_limit;
	bool up = true;
	while(1) {
		adc_.start(0b00000111);

		cmt_.sync();

		// A/D 変換開始
		adc_.sync();

device::PORTB::PODR.B7 = 0; // LED On

		int32_t ref = static_cast<int32_t>(adc_.get(0)); // 指令電圧
		int32_t out = static_cast<int32_t>(adc_.get(1)); // 出力電圧
		int32_t inp = static_cast<int32_t>(adc_.get(2)); // 入力電圧

// int32_t gain = static_cast<int32_t>(adc_.get(0));
int32_t gain = 130;

		// 三角波
#if 0
		if(up) {
			ref += 1;
		} else {
			ref -= 1;
		}

		if(ref > 1700) {
			up = false;
			ref = 1700;
		} else if(ref < 200) {
			up = true;
			ref = 200;
		}
#endif

		int32_t dif = ref - out;  // 誤差
		// PWM の制御量に対するスレッショルド
		int32_t d = dif * gain / inp;
		val += d;
		cpv = val / 8;
		// 出力リミッター
		if(cpv < low_limit) cpv = low_limit;
		else if(cpv > high_limit) cpv = high_limit;

		gpt_.set_a(cpv);
		uint16_t ofs = (512 - cpv) / 4;
		gpt_.set_ad_a(cpv + ofs);	// A/D 変換開始タイミング

device::PORTB::PODR.B7 = 1; // LED Off

#if 0
		monitor_.service();

		++cnt;
		if(cnt >= 1000) {
			cnt = 0;
			prn_voltage_("Inp: ", inp);
			prn_voltage_("Ref: ", ref);
			prn_voltage_("Dif: ", dif);
			prn_voltage_("Out: ", out);
			prn_value_("PWM: ", cpv);
        }
#endif
#if 0
		++led;
		if(led >= 700) led = 0;
		if(led < 350) {
			device::PORTB::PODR.B7 = 1; // LED Off
		} else {
			device::PORTB::PODR.B7 = 0; // LED On
		}
#endif
	}
}
<commit_msg>update comment<commit_after>//=====================================================================//
/*! @file
    @brief  RX メイン @n
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "main.hpp"
#include "rx/rx63x/system.hpp"
#include "rx/rx63x/port.hpp"
#include "rx/rx63x/mpc.hpp"
#include "rx/cmt_io.hpp"
#include "rx/sci_io.hpp"
#include "rx/gpt_io.hpp"
#include "rx/adc_io.hpp"
#include "rx/chout.hpp"
#include "inv_monitor.hpp"

namespace root {
	device::cmt_io<device::CMT0>  cmt_;
	device::sci_io<device::SCI1, 256, 256>  sci_;
	device::gpt_io<device::GPT0>  gpt_;
	device::adc_io<device::S12AD> adc_;
	utils::chout chout_;
	utils::inv_monitor monitor_;
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字出力
	@param[in]	ch	文字コード
 */
//-----------------------------------------------------------------//
void sci_putch(char ch)
{
	root::sci_.putch(ch);
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字列出力
	@param[in]	str	文字列
 */
//-----------------------------------------------------------------//
void sci_puts(const char *str)
{
	root::sci_.puts(str);
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字入力
	@return 文字コード
 */
//-----------------------------------------------------------------//
char sci_getch(void)
{
	return root::sci_.getch();
}

//-----------------------------------------------------------------//
/*!
	@brief	SCI 文字入力数を取得
	@return 入力文字数
 */
//-----------------------------------------------------------------//
uint32_t sci_length(void)
{
	return root::sci_.length();
}

//-----------------------------------------------------------------//
/*!
	@brief	10ms 単位タイマー
 */
//-----------------------------------------------------------------//
void delay_10ms(uint32_t n)
{
	while(n > 0) {
		root::cmt_.sync();
		--n;
	}
}

void prn_voltage_(const char* info, int32_t v)
{
	int32_t vv = v * 15 * 100 / 4096;
	int32_t mod = vv % 100;
	if(mod < 0) mod = -mod;
	root::chout_.suppress_char(' ');
	root::chout_.set_length(0);
	root::chout_ << info << (vv / 100) << '.';
	root::chout_.suppress_char('0');
	root::chout_.set_length(2);
	root::chout_ << mod << utils::chout::endl;
}

void prn_value_(const char* info, int32_t v)
{
	root::chout_.suppress_char(' ');
	root::chout_.set_length(0);
	root::chout_ << info << v << utils::chout::endl;
}

static volatile uint8_t dummy_;

static void wait_()
{
	// とりあえず無駄ループ
	for(uint32_t i = 0; i < 5000; ++i) {
		i += dummy_ & 0;
	}
}
int main(int argc, char** argv);

int main(int argc, char** argv)
{
	using namespace root;

	device::SYSTEM::PRCR = 0xa503;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MOSCWTCR.MSTS = 0b01101;	// 131072 サイクル待ち
	device::SYSTEM::MOSCCR.MOSTP = 0;			// メインクロック発振器動作
	dummy_ = device::SYSTEM::MOSCCR.MOSTP();
	device::SYSTEM::MOFCR.MOFXIN = 1;			// メインクロック強制発振
	dummy_ = device::SYSTEM::MOFCR.MOFXIN();
	wait_();

	device::SYSTEM::PLLCR.STC = 0xf;			// PLL 16 倍(192MHz)
	device::SYSTEM::PLLWTCR.PSTS = 0b01010;		// 131072 サイクル待ち
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	wait_();

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(3)		// 1/8 (192/8=24)
						  | device::SYSTEM::SCKCR.ICK.b(1)		// 1/2 (192/2=96)
						  | device::SYSTEM::SCKCR.BCK.b(2)		// 1/4 (192/4=48)
						  | device::SYSTEM::SCKCR.PCKA.b(1)		// 1/2 (192/2=96)
						  | device::SYSTEM::SCKCR.PCKB.b(2)		// 1/4 (192/4=48)
						  | device::SYSTEM::SCKCR.PCKC.b(2)		// 1/4 (192/8=48)
						  | device::SYSTEM::SCKCR.PCKD.b(2);	// 1/4 (192/8=48)
	device::SYSTEM::SCKCR3.CKSEL = 4;	///< PLL 回路選択

	// Signal LED 出力設定
	device::PORTB::PDR.B7 = 1; // PORTB:B7 output
	device::PORTB::PODR.B7 = 1; // LED Off

	// SCI1 の初期化（PD5:RXD1:input, PD3:TXD1:output）
	device::PORTD::PDR.B3 = 1;
	device::MPC::PWPR.B0WI = 0;				// PWPR 書き込み許可
	device::MPC::PWPR.PFSWE = 1;			// PxxPFS 書き込み許可
	device::MPC::PD3PFS.PSEL = 0b01010;		// TXD1 設定
	device::MPC::PD5PFS.PSEL = 0b01010;		// RXD1 設定
	device::MPC::PWPR = device::MPC::PWPR.B0WI.b();	// MPC 書き込み禁止
	device::PORTD::PMR.B3 = 1;
	device::PORTD::PMR.B5 = 1;
	static const uint8_t sci_irq_level = 1;
	sci_.initialize(sci_irq_level);
	sci_.start(115200);

	// GPT0 設定 (GTIOC0A: P71:38, PD7:12)(GTIOC0B: P74:35, PD6:13)
	device::PORT7::PDR.B1 = 1;			// output
	device::SYSTEM::MSTPCRA.MSTPA7 = 0; // GPT0..3 モジュール有効
	device::MPC::PWPR.B0WI = 0;			// PWPR 書き込み許可
	device::MPC::PWPR.PFSWE = 1;		// PxxPFS 書き込み許可
	device::MPC::P71PFS.PSEL = 0b0110;	// GTIOC0A 設定
	device::MPC::PWPR = device::MPC::PWPR.B0WI.b();	// MPC 書き込み禁止
	device::PORT7::PMR.B1 = 1;
	gpt_.start();	// PWM start
	gpt_.set_r(512 - 1);
	gpt_.set_a(256);

	// S12AD 設定 P40(56), P41(55), P42(54)
	device::SYSTEM::MSTPCRA.MSTPA17 = 0; // S12AD モジュール有効
	device::MPC::PWPR.B0WI = 0;			 // PWPR 書き込み許可
	device::MPC::PWPR.PFSWE = 1;		 // PxxPFS 書き込み許可
	device::MPC::P40PFS.ASEL = 1;	     // アナログ入力設定
	device::MPC::P41PFS.ASEL = 1;	     // アナログ入力設定
	device::MPC::PWPR = device::MPC::PWPR.B0WI.b();	// MPC 書き込み禁止

	// タイマー設定
	cmt_.set_clock(F_PCKB);
	uint8_t cmt_irq_level = 3;
	cmt_.initialize(93750, cmt_irq_level);

	cmt_.sync();

	monitor_.initialize();

///	device::SYSTEM::PRCR = 0xa500;	///< クロック、低消費電力、関係書き込み禁止

	for(int i = 0; i < 10; ++i) {
		adc_.start(0b00000111);
		cmt_.sync();
		adc_.sync();
		int32_t v = static_cast<int32_t>(adc_.get(0));
		prn_value_("Ch0: ", v);
	}

	uint32_t cnt = 0;
	uint32_t led = 0;

	int32_t ds = 0;

	int32_t ref = 300;

	int32_t val = 0;

	int32_t low_limit = 10; // 0.23V at 12V input
	int32_t high_limit = 500; // 11.72V at 12V input
	int32_t cpv = low_limit;
	bool up = true;
	while(1) {
		adc_.start(0b00000111);

		cmt_.sync();

		// A/D 変換開始
		adc_.sync();

device::PORTB::PODR.B7 = 0; // LED On

		int32_t ref = static_cast<int32_t>(adc_.get(0)); // 指令電圧
		int32_t out = static_cast<int32_t>(adc_.get(1)); // 出力電圧
		int32_t inp = static_cast<int32_t>(adc_.get(2)); // 入力電圧

// int32_t gain = static_cast<int32_t>(adc_.get(0));
int32_t gain = 130;

		// 三角波
#if 0
		if(up) {
			ref += 1;
		} else {
			ref -= 1;
		}

		if(ref > 1700) {
			up = false;
			ref = 1700;
		} else if(ref < 200) {
			up = true;
			ref = 200;
		}
#endif

		int32_t dif = ref - out;  // 誤差
		// PWM の制御量に対するスレッショルド
		int32_t d = dif * gain / inp;
		val += d;
		cpv = val / 8;
		// 出力リミッター
		if(cpv < low_limit) cpv = low_limit;
		else if(cpv > high_limit) cpv = high_limit;

		gpt_.set_a(cpv);
		uint16_t ofs = (512 - cpv) / 4;
		gpt_.set_ad_a(cpv + ofs);	// A/D 変換開始タイミング

device::PORTB::PODR.B7 = 1; // LED Off

#if 0
		monitor_.service();

		++cnt;
		if(cnt >= 1000) {
			cnt = 0;
			prn_voltage_("Inp: ", inp);
			prn_voltage_("Ref: ", ref);
			prn_voltage_("Dif: ", dif);
			prn_voltage_("Out: ", out);
			prn_value_("PWM: ", cpv);
        }
#endif
#if 0
		++led;
		if(led >= 700) led = 0;
		if(led < 350) {
			device::PORTB::PODR.B7 = 1; // LED Off
		} else {
			device::PORTB::PODR.B7 = 0; // LED On
		}
#endif
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014—2016 David Wicks, sansumbrella.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once
#include <vector>
#include "Phrase.hpp"
#include "UnitBezier.h"
#include "TimeType.h"

namespace choreograph
{

class Curve
{
public:
  enum Type {
    Bezier,
    Hold,
    Linear
  };
  float solve(float t) const;
  void  setType(Type type) { _type = type; }
  void  hold() { _type = Hold; }
  BezierInterpolant& bezier() { _type = Bezier; return _bezier; }
private:
  Type              _type = Linear;
  BezierInterpolant _bezier;
};

float Curve::solve(float t) const
{
  switch (_type) {
    case Bezier:
      return _bezier.solve(t);
    break;
    case Hold:
      return 0.0f;
    break;
    case Linear:
      return t;
    break;
    default:
      return t;
    break;
  }
}

///
/// Simple channel concept with bezier interpolation between keys.
/// Goals:
/// - Easy serialization
/// - Easy to create graphical manipulation tools.
///   - Support direct manipulation of animation data.
///   - Avoid deeply nested information. Flat hierarchy.
/// - Flexible enough to create an AfterEffects-style timeline.
///
/// Good for animating single values, like floats or quaternions.
/// For vector types, use a channel per component (and maybe add a group type to associate them).
/// Grouping type could be a manipulator/animator type class that reads/writes multiple channels.
///
template <typename T>
class Channel
{
public:
  struct Key {
    Key(T value, Time time):
      value(value),
      time(time)
    {}
    T    value;
    Time time;
  };

  Channel() = default;

  /// Return the value of the channel at a given time.
  T value(Time at_time) const;
  /// Return the interpolated value between two keys.
  /// If you keep track of keys yourself, this is faster.
  T interpolatedValue(size_t curve_index, Time at_time) const;

  /// Returns the index of the starting key for the current time.
  /// The curve lies between two keys.
  size_t index(Time at_time) const;
  size_t lastIndex() const { return _keys.empty() ? 0 : _keys.size() - 1; }

  /// Append a key to the list of keys, positioned at \offset time after the previous key.
  Channel& appendKeyAfter(T value, Time offset) {
    if (! _keys.empty()) {
      _curves.emplace_back();
    }
    _keys.emplace_back(value, duration() + offset);
    return *this;
  }
  /// Insert a key at the given time.
  Channel& insertKey(T value, Time at_time);

  Time     duration() const { return _keys.empty() ? 0 : _keys.back().time; }
  const std::vector<Key>&   keys() const { return _keys; }
  const std::vector<Curve>& curves() const { return _curves; }

private:
  std::vector<Key>   _keys;
  // may make polymorphic in future (like phrases are). Basically just an ease fn.
  // Compare std::function<float (float)> for max flexibility against custom class.
  std::vector<Curve> _curves;
};

#pragma mark - Channel Template Implementation

template <typename T>
size_t Channel<T>::index(Time at_time) const {

  if( at_time <= 0 ) {
    return 0;
  }
  else if ( at_time >= this->duration() ) {
    return lastIndex();
  }

  for (auto i = 0; i < _keys.size() - 1; i += 1) {
    auto &a = _keys[i], &b = _keys[i + 1];
    if (a.time <= at_time && b.time >= at_time) {
      return i;
    }
  }
  return lastIndex();
}

template <typename T>
T Channel<T>::value(Time at_time) const {
  if (at_time >= duration()) {
    return _keys.back().value;
  }
  else if (at_time <= 0.0) {
    return _keys.front().value;
  }

  return interpolatedValue(index(at_time), at_time);
}

template <typename T>
T Channel<T>::interpolatedValue(size_t curve_index, Time at_time) const {
  auto &a = _keys[curve_index];
  auto &b = _keys[curve_index + 1];
  auto &c = _curves[curve_index];

  auto x = (at_time - a.time) / (b.time - a.time);
  auto t = c.solve(x);
  return lerpT(a.value, b.value, t);
}

template <typename T>
Channel<T>& Channel<T>::insertKey(T value, Time at_time) {
  if (_keys.empty()) {
    _keys.emplace_back(value, at_time);
    return *this;
  }

  auto i = index(at_time);
  _curves.insert(_curves.begin() + i, {});
  _keys.insert(_keys.begin() + i + 1, {value, at_time});

  return *this;
}

} // namepsace choreograph
<commit_msg>Expose mutable contents.<commit_after>/*
 * Copyright (c) 2014—2016 David Wicks, sansumbrella.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once
#include <vector>
#include "Phrase.hpp"
#include "UnitBezier.h"
#include "TimeType.h"

namespace choreograph
{

class Curve
{
public:
  enum Type {
    Bezier,
    Hold,
    Linear
  };
  float solve(float t) const;
  void  setType(Type type) { _type = type; }
  void  hold() { _type = Hold; }
  BezierInterpolant&       bezier() { _type = Bezier; return _bezier; }
private:
  Type              _type = Linear;
  BezierInterpolant _bezier;
};

float Curve::solve(float t) const
{
  switch (_type) {
    case Bezier:
      return _bezier.solve(t);
    break;
    case Hold:
      return 0.0f;
    break;
    case Linear:
      return t;
    break;
    default:
      return t;
    break;
  }
}

///
/// Simple channel concept with bezier interpolation between keys.
/// Goals:
/// - Easy serialization
/// - Easy to create graphical manipulation tools.
///   - Support direct manipulation of animation data.
///   - Avoid deeply nested information. Flat hierarchy.
/// - Flexible enough to create an AfterEffects-style timeline.
///
/// Good for animating single values, like floats or quaternions.
/// For vector types, use a channel per component (and maybe add a group type to associate them).
/// Grouping type could be a manipulator/animator type class that reads/writes multiple channels.
///
template <typename T>
class Channel
{
public:
  struct Key {
    Key(T value, Time time):
      value(value),
      time(time)
    {}
    T    value;
    Time time;
  };

  Channel() = default;

  /// Return the value of the channel at a given time.
  T value(Time at_time) const;
  /// Return the interpolated value between two keys.
  /// If you keep track of keys yourself, this is faster.
  T interpolatedValue(size_t curve_index, Time at_time) const;

  /// Returns the index of the starting key for the current time.
  /// The curve lies between two keys.
  size_t index(Time at_time) const;
  size_t lastIndex() const { return _keys.empty() ? 0 : _keys.size() - 1; }

  /// Append a key to the list of keys, positioned at \offset time after the previous key.
  Channel& appendKeyAfter(T value, Time offset) {
    if (! _keys.empty()) {
      _curves.emplace_back();
    }
    _keys.emplace_back(value, duration() + offset);
    return *this;
  }
  /// Insert a key at the given time.
  Channel& insertKey(T value, Time at_time);

  Time     duration() const { return _keys.empty() ? 0 : _keys.back().time; }
  const std::vector<Key>&   keys() const { return _keys; }
  const std::vector<Curve>& curves() const { return _curves; }

  std::vector<Key>&   mutableKeys() { return _keys; }
  std::vector<Curve>& mutableCurves() { return _curves; }

private:
  std::vector<Key>   _keys;
  // may make polymorphic in future (like phrases are). Basically just an ease fn.
  // Compare std::function<float (float)> for max flexibility against custom class.
  std::vector<Curve> _curves;
};

#pragma mark - Channel Template Implementation

template <typename T>
size_t Channel<T>::index(Time at_time) const {

  if( at_time <= 0 ) {
    return 0;
  }
  else if ( at_time >= this->duration() ) {
    return lastIndex();
  }

  for (auto i = 0; i < _keys.size() - 1; i += 1) {
    auto &a = _keys[i], &b = _keys[i + 1];
    if (a.time <= at_time && b.time >= at_time) {
      return i;
    }
  }
  return lastIndex();
}

template <typename T>
T Channel<T>::value(Time at_time) const {
  if (at_time >= duration()) {
    return _keys.back().value;
  }
  else if (at_time <= 0.0) {
    return _keys.front().value;
  }

  return interpolatedValue(index(at_time), at_time);
}

template <typename T>
T Channel<T>::interpolatedValue(size_t curve_index, Time at_time) const {
  auto &a = _keys[curve_index];
  auto &b = _keys[curve_index + 1];
  auto &c = _curves[curve_index];

  auto x = (at_time - a.time) / (b.time - a.time);
  auto t = c.solve(x);
  return lerpT(a.value, b.value, t);
}

template <typename T>
Channel<T>& Channel<T>::insertKey(T value, Time at_time) {
  if (_keys.empty()) {
    _keys.emplace_back(value, at_time);
    return *this;
  }

  auto i = index(at_time);
  _curves.insert(_curves.begin() + i, {});
  _keys.insert(_keys.begin() + i + 1, {value, at_time});

  return *this;
}

} // namepsace choreograph
<|endoftext|>