mirror of https://github.com/KLayout/klayout.git
WIP: bugfixes, refactoring.
This commit is contained in:
parent
2ec712b104
commit
f9aa89a0b3
|
|
@ -127,6 +127,12 @@
|
||||||
<file alias="folder_12.png">images/folder_12.png</file>
|
<file alias="folder_12.png">images/folder_12.png</file>
|
||||||
<file alias="file_12.png">images/file_12.png</file>
|
<file alias="file_12.png">images/file_12.png</file>
|
||||||
<file alias="empty_12.png">images/empty_12.png</file>
|
<file alias="empty_12.png">images/empty_12.png</file>
|
||||||
|
<file alias="fit_front.png">images/fit_front.png</file>
|
||||||
|
<file alias="fit_back.png">images/fit_back.png</file>
|
||||||
|
<file alias="fit_left.png">images/fit_left.png</file>
|
||||||
|
<file alias="fit_right.png">images/fit_right.png</file>
|
||||||
|
<file alias="fit_top.png">images/fit_top.png</file>
|
||||||
|
<file alias="fit_bottom.png">images/fit_bottom.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/syntax">
|
<qresource prefix="/syntax">
|
||||||
<file alias="ruby.xml">syntax/ruby.xml</file>
|
<file alias="ruby.xml">syntax/ruby.xml</file>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>576</width>
|
<width>854</width>
|
||||||
<height>649</height>
|
<height>665</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
|
@ -29,17 +29,249 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>9</number>
|
<number>9</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="zoom_slider">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="zoom_factor">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>%</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="fit_left">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||||
|
<normaloff>:/fit_left.png</normaloff>:/fit_left.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="fit_front">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||||
|
<normaloff>:/fit_front.png</normaloff>:/fit_front.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="fit_right">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||||
|
<normaloff>:/fit_right.png</normaloff>:/fit_right.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="fit_back">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||||
|
<normaloff>:/fit_back.png</normaloff>:/fit_back.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="fit_top">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||||
|
<normaloff>:/fit_top.png</normaloff>:/fit_top.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="fit_bottom">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||||
|
<normaloff>:/fit_bottom.png</normaloff>:/fit_bottom.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="lay::D25ViewWidget" name="d25_view"/>
|
<widget class="lay::D25ViewWidget" name="d25_view"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QFrame" name="frame_2">
|
||||||
<property name="orientation">
|
<property name="sizePolicy">
|
||||||
<enum>Qt::Horizontal</enum>
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons">
|
<property name="frameShape">
|
||||||
<set>QDialogButtonBox::Close</set>
|
<enum>QFrame::NoFrame</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Press and hold SHIFT for top view</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Close</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
@ -51,10 +283,9 @@
|
||||||
<header>layD25ViewWidget.h</header>
|
<header>layD25ViewWidget.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<resources>
|
||||||
<tabstop>buttonBox</tabstop>
|
<include location="../../../../lay/lay/layResources.qrc"/>
|
||||||
</tabstops>
|
</resources>
|
||||||
<resources/>
|
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>buttonBox</sender>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "layD25Camera.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
|
||||||
|
namespace lay
|
||||||
|
{
|
||||||
|
|
||||||
|
D25Camera::D25Camera ()
|
||||||
|
{
|
||||||
|
init ();
|
||||||
|
}
|
||||||
|
|
||||||
|
D25Camera::~D25Camera ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
D25Camera::init ()
|
||||||
|
{
|
||||||
|
m_fov = 90.0;
|
||||||
|
m_cam_azimuth = m_cam_elevation = 0.0;
|
||||||
|
m_top_view = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
D25Camera::camera_reset ()
|
||||||
|
{
|
||||||
|
init ();
|
||||||
|
camera_changed ();
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
D25Camera::cam_fov () const
|
||||||
|
{
|
||||||
|
return m_fov; // @@@
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
D25Camera::cam_dist () const
|
||||||
|
{
|
||||||
|
return 4.0; // @@@
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector3D
|
||||||
|
D25Camera::cam_direction () const
|
||||||
|
{
|
||||||
|
return cam_trans ().inverted ().map (QVector3D (0, 0, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector3D
|
||||||
|
D25Camera::cam_position () const
|
||||||
|
{
|
||||||
|
return cam_direction () * -cam_dist ();
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
D25Camera::cam_azimuth () const
|
||||||
|
{
|
||||||
|
return m_cam_azimuth;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
D25Camera::cam_elevation () const
|
||||||
|
{
|
||||||
|
return m_top_view ? -90.0 : m_cam_elevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMatrix4x4
|
||||||
|
D25Camera::cam_perspective () const
|
||||||
|
{
|
||||||
|
QMatrix4x4 t;
|
||||||
|
t.perspective (cam_fov (), aspect_ratio (), 0.1f, 10000.0f);
|
||||||
|
t.translate (QVector3D (0.0, 0.0, -cam_dist ()));
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMatrix4x4
|
||||||
|
D25Camera::cam_trans () const
|
||||||
|
{
|
||||||
|
QMatrix4x4 t;
|
||||||
|
t.rotate (-cam_elevation (), 1.0, 0.0, 0.0);
|
||||||
|
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HDR_layD25Camera
|
||||||
|
#define HDR_layD25Camera
|
||||||
|
|
||||||
|
#include "layPluginCommon.h"
|
||||||
|
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
#include <QVector3D>
|
||||||
|
|
||||||
|
namespace lay
|
||||||
|
{
|
||||||
|
|
||||||
|
class LAY_PLUGIN_PUBLIC D25Camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
D25Camera ();
|
||||||
|
virtual ~D25Camera ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the position of the camera objective in the scene coordinate system
|
||||||
|
*/
|
||||||
|
QVector3D cam_position () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the direction the camera looks into in the scene coordinate system
|
||||||
|
*/
|
||||||
|
QVector3D cam_direction () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the perspective part of the transformation applied transform scene coordinates into the image plane
|
||||||
|
* The full transformation for scene to image plane is cam_perspective * cam_trans.
|
||||||
|
*/
|
||||||
|
QMatrix4x4 cam_perspective () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the azimuth/elevation part of the transformation applied transform scene coordinates into the image plane
|
||||||
|
* The full transformation for scene to image plane is cam_perspective * cam_trans.
|
||||||
|
*/
|
||||||
|
QMatrix4x4 cam_trans () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the distance of the objective in scene coordinates
|
||||||
|
*/
|
||||||
|
double cam_dist () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the field of view of the camera
|
||||||
|
* The field of view is the objective opening angle.
|
||||||
|
*/
|
||||||
|
double cam_fov () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a flag indicating whether top view is enabled
|
||||||
|
* In "top view" mode, the elevation is fixed to -90 degree.
|
||||||
|
*/
|
||||||
|
bool top_view () const
|
||||||
|
{
|
||||||
|
return m_top_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a flag indicating whether top view is enabled
|
||||||
|
*/
|
||||||
|
void set_top_view (bool f)
|
||||||
|
{
|
||||||
|
m_top_view = f;
|
||||||
|
camera_changed ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the elevation angle
|
||||||
|
* A negative angle means the camera looks down, a positive angle means it looks up.
|
||||||
|
*/
|
||||||
|
double cam_elevation () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the elevation angle
|
||||||
|
*/
|
||||||
|
void set_cam_elevation (double e)
|
||||||
|
{
|
||||||
|
m_cam_elevation = e;
|
||||||
|
camera_changed ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the azimuth angle
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
double cam_azimuth () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the azimuth angle
|
||||||
|
*/
|
||||||
|
void set_cam_azimuth (double a)
|
||||||
|
{
|
||||||
|
m_cam_azimuth = a;
|
||||||
|
camera_changed ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets the camera's orientation
|
||||||
|
*/
|
||||||
|
void camera_reset ();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void camera_changed () { }
|
||||||
|
virtual double aspect_ratio () const { return 1.0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_cam_azimuth, m_cam_elevation;
|
||||||
|
bool m_top_view;
|
||||||
|
QVector3D m_displacement;
|
||||||
|
double m_fov;
|
||||||
|
|
||||||
|
void init ();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -21,3 +21,4 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "layD25MemChunks.h"
|
#include "layD25MemChunks.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#define HDR_layD25MemChunks
|
#define HDR_layD25MemChunks
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
|
||||||
#include "tlObject.h"
|
#include "tlObject.h"
|
||||||
#include <string.h> // for memcpy
|
#include <string.h> // for memcpy
|
||||||
|
|
@ -31,6 +32,19 @@
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template <class Obj>
|
||||||
|
struct gl_type2enum
|
||||||
|
{
|
||||||
|
GLenum operator() () const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct gl_type2enum<float>
|
||||||
|
{
|
||||||
|
GLenum operator() () const { return GL_FLOAT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Provides a semi-contiguous array of objects
|
* @brief Provides a semi-contiguous array of objects
|
||||||
*
|
*
|
||||||
|
|
@ -201,6 +215,25 @@ public:
|
||||||
mp_last_chunk->m_objects [mp_last_chunk->m_len++] = element;
|
mp_last_chunk->m_objects [mp_last_chunk->m_len++] = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds two elements
|
||||||
|
*/
|
||||||
|
void add (const Obj &e1, const Obj &e2)
|
||||||
|
{
|
||||||
|
add (e1);
|
||||||
|
add (e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds three elements
|
||||||
|
*/
|
||||||
|
void add (const Obj &e1, const Obj &e2, const Obj &e3)
|
||||||
|
{
|
||||||
|
add (e1);
|
||||||
|
add (e2);
|
||||||
|
add (e3);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief begin iterator
|
* @brief begin iterator
|
||||||
*/
|
*/
|
||||||
|
|
@ -211,6 +244,17 @@ public:
|
||||||
*/
|
*/
|
||||||
iterator end () const { return iterator (); }
|
iterator end () const { return iterator (); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw to the given context
|
||||||
|
*/
|
||||||
|
void draw_to (QOpenGLFunctions *ctx, GLuint location, GLenum mode) const
|
||||||
|
{
|
||||||
|
for (iterator c = begin (); c != end (); ++c) {
|
||||||
|
ctx->glVertexAttribPointer (location, 3, gl_type2enum<Obj> () (), GL_FALSE, 0, c->front ());
|
||||||
|
ctx->glDrawArrays (mode, 0, c->size () / 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
chunk *mp_chunks;
|
chunk *mp_chunks;
|
||||||
chunk *mp_last_chunk;
|
chunk *mp_last_chunk;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const double initial_elevation = 3.0;
|
||||||
|
|
||||||
D25View::D25View (QWidget *parent)
|
D25View::D25View (QWidget *parent)
|
||||||
: QDialog (parent)
|
: QDialog (parent)
|
||||||
{
|
{
|
||||||
|
|
@ -41,6 +43,13 @@ D25View::D25View (QWidget *parent)
|
||||||
mp_ui->d25_view->setFocusPolicy (Qt::StrongFocus);
|
mp_ui->d25_view->setFocusPolicy (Qt::StrongFocus);
|
||||||
mp_ui->d25_view->setFocus ();
|
mp_ui->d25_view->setFocus ();
|
||||||
// @@@
|
// @@@
|
||||||
|
|
||||||
|
connect (mp_ui->fit_back, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
|
||||||
|
connect (mp_ui->fit_front, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
|
||||||
|
connect (mp_ui->fit_left, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
|
||||||
|
connect (mp_ui->fit_right, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
|
||||||
|
connect (mp_ui->fit_top, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
|
||||||
|
connect (mp_ui->fit_bottom, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
D25View::~D25View ()
|
D25View::~D25View ()
|
||||||
|
|
@ -55,6 +64,10 @@ D25View::exec_dialog (lay::LayoutView *view)
|
||||||
mp_view.reset (view);
|
mp_view.reset (view);
|
||||||
mp_ui->d25_view->attach_view (view);
|
mp_ui->d25_view->attach_view (view);
|
||||||
|
|
||||||
|
mp_ui->d25_view->reset ();
|
||||||
|
mp_ui->d25_view->set_cam_azimuth (0.0);
|
||||||
|
mp_ui->d25_view->set_cam_elevation (initial_elevation);
|
||||||
|
|
||||||
int ret = QDialog::exec ();
|
int ret = QDialog::exec ();
|
||||||
|
|
||||||
mp_ui->d25_view->attach_view (0);
|
mp_ui->d25_view->attach_view (0);
|
||||||
|
|
@ -62,6 +75,36 @@ D25View::exec_dialog (lay::LayoutView *view)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
D25View::fit_button_clicked ()
|
||||||
|
{
|
||||||
|
double azimuth = mp_ui->d25_view->cam_azimuth ();
|
||||||
|
double elevation = mp_ui->d25_view->cam_elevation ();
|
||||||
|
|
||||||
|
if (sender () == mp_ui->fit_back) {
|
||||||
|
azimuth = -180.0;
|
||||||
|
elevation = -initial_elevation;
|
||||||
|
} else if (sender () == mp_ui->fit_front) {
|
||||||
|
azimuth = 0.0;
|
||||||
|
elevation = -initial_elevation;
|
||||||
|
} else if (sender () == mp_ui->fit_left) {
|
||||||
|
azimuth = 90.0;
|
||||||
|
elevation = -initial_elevation;
|
||||||
|
} else if (sender () == mp_ui->fit_right) {
|
||||||
|
azimuth = -90.0;
|
||||||
|
elevation = -initial_elevation;
|
||||||
|
} else if (sender () == mp_ui->fit_top) {
|
||||||
|
elevation = -90;
|
||||||
|
} else if (sender () == mp_ui->fit_bottom) {
|
||||||
|
elevation = 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_ui->d25_view->set_cam_azimuth (azimuth);
|
||||||
|
mp_ui->d25_view->set_cam_elevation (elevation);
|
||||||
|
|
||||||
|
mp_ui->d25_view->fit ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
D25View::accept ()
|
D25View::accept ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,9 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void accept ();
|
void accept ();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void fit_button_clicked ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::D25View *mp_ui;
|
Ui::D25View *mp_ui;
|
||||||
tl::weak_ptr<lay::LayoutView> mp_view;
|
tl::weak_ptr<lay::LayoutView> mp_view;
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ cutpoint_line_with_face (const QVector3D &line, const QVector3D &dir, const QVec
|
||||||
|
|
||||||
static bool somewhat_perpendicular (const QVector3D &a, const QVector3D &b)
|
static bool somewhat_perpendicular (const QVector3D &a, const QVector3D &b)
|
||||||
{
|
{
|
||||||
// returns true if a and b are perpendicular within 30 degree
|
// returns true if a and b are perpendicular within +/-30 degree
|
||||||
return fabs (QVector3D::dotProduct (a, b)) < 0.5 * a.length () * b.length ();
|
return fabs (QVector3D::dotProduct (a, b)) < 0.5 * a.length () * b.length ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,146 @@ namespace lay
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
D25InteractionMode::D25InteractionMode (D25ViewWidget *view)
|
||||||
|
: mp_view (view)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
D25InteractionMode::~D25InteractionMode ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class D25PanInteractionMode
|
||||||
|
: public D25InteractionMode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
D25PanInteractionMode (D25ViewWidget *widget, const QPoint &pos)
|
||||||
|
: D25InteractionMode (widget), m_start_pos (pos)
|
||||||
|
{
|
||||||
|
m_start_displacement = widget->displacement ();
|
||||||
|
|
||||||
|
double px = (pos.x () - widget->width () / 2) * 2.0 / widget->width ();
|
||||||
|
double py = -(pos.y () - widget->height () / 2) * 2.0 / widget->height ();
|
||||||
|
|
||||||
|
// compute vector of line of sight
|
||||||
|
std::pair<QVector3D, QVector3D> ray = camera_normal (view ()->cam_perspective () * view ()->cam_trans (), px, py);
|
||||||
|
|
||||||
|
// by definition the ray goes through the camera position
|
||||||
|
QVector3D hp = widget->hit_point_with_scene (ray.second);
|
||||||
|
|
||||||
|
m_focus_dist = (widget->cam_position () - hp).length ();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~D25PanInteractionMode ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void mouse_move (QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QPoint d = event->pos () - m_start_pos;
|
||||||
|
double f = tan ((view ()->cam_fov () / 2) / 180.0 * M_PI) * m_focus_dist * 2.0 / double (view ()->height ());
|
||||||
|
double dx = d.x () * f;
|
||||||
|
double dy = -d.y () * f;
|
||||||
|
|
||||||
|
QVector3D xv (cos (view ()->cam_azimuth () * M_PI / 180.0), 0.0, sin (view ()->cam_azimuth () * M_PI / 180.0));
|
||||||
|
double re = sin (view ()->cam_elevation () * M_PI / 180.0);
|
||||||
|
QVector3D yv (-re * xv.z (), cos (view ()->cam_elevation () * M_PI / 180.0), re * xv.x ());
|
||||||
|
QVector3D drag = xv * dx + yv * dy;
|
||||||
|
|
||||||
|
view ()->set_displacement (m_start_displacement + drag / view ()->scale_factor ());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPoint m_start_pos;
|
||||||
|
double m_focus_dist;
|
||||||
|
QVector3D m_start_displacement;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class D25Rotate2DInteractionMode
|
||||||
|
: public D25InteractionMode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
D25Rotate2DInteractionMode (D25ViewWidget *widget, const QPoint &pos)
|
||||||
|
: D25InteractionMode (widget), m_start_pos (pos)
|
||||||
|
{
|
||||||
|
m_start_cam_azimuth = widget->cam_azimuth ();
|
||||||
|
m_start_cam_elevation = widget->cam_elevation ();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~D25Rotate2DInteractionMode ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void mouse_move (QMouseEvent *event)
|
||||||
|
{
|
||||||
|
// fixed focus point for rotation
|
||||||
|
double focus_dist = 2.0;
|
||||||
|
|
||||||
|
QPoint d = event->pos () - m_start_pos;
|
||||||
|
double f = tan ((view ()->cam_fov () / 2) / 180.0 * M_PI) * focus_dist * 2.0 / double (view ()->height ());
|
||||||
|
double dx = d.x () * f;
|
||||||
|
double dy = -d.y () * f;
|
||||||
|
|
||||||
|
double da = dx / (view ()->cam_dist () - focus_dist) * 180.0 / M_PI;
|
||||||
|
view ()->set_cam_azimuth (m_start_cam_azimuth + da);
|
||||||
|
|
||||||
|
double de = dy / (view ()->cam_dist () - focus_dist) * 180.0 / M_PI;
|
||||||
|
view ()->set_cam_elevation (m_start_cam_elevation + de);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPoint m_start_pos;
|
||||||
|
double m_start_cam_azimuth, m_start_cam_elevation;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class D25RotateAzimuthInteractionMode
|
||||||
|
: public D25InteractionMode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
D25RotateAzimuthInteractionMode (D25ViewWidget *widget, const QPoint &pos)
|
||||||
|
: D25InteractionMode (widget), m_start_pos (pos)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~D25RotateAzimuthInteractionMode ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void mouse_move (QMouseEvent *event)
|
||||||
|
{
|
||||||
|
// simple change of azimuth only - with center in the middle
|
||||||
|
|
||||||
|
QPoint m = event->pos () - m_start_pos;
|
||||||
|
QVector3D p (m_start_pos.x () - view ()->width () / 2, -m_start_pos.y () + view ()->height () / 2, 0);
|
||||||
|
QVector3D d (m.x (), -m.y (), 0);
|
||||||
|
|
||||||
|
double cp = QVector3D::crossProduct (p, p + d).z () / p.length () / (p + d).length ();
|
||||||
|
cp = std::max (-1.0, std::min (1.0, cp));
|
||||||
|
double da = asin (cp) * 180.0 / M_PI;
|
||||||
|
|
||||||
|
view ()->set_cam_azimuth (view ()->cam_azimuth () + da);
|
||||||
|
m_start_pos = event->pos ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPoint m_start_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
D25ViewWidget::D25ViewWidget (QWidget *parent)
|
D25ViewWidget::D25ViewWidget (QWidget *parent)
|
||||||
: QOpenGLWidget (parent),
|
: QOpenGLWidget (parent),
|
||||||
m_shapes_program (0)
|
m_shapes_program (0)
|
||||||
|
|
@ -74,13 +214,9 @@ void
|
||||||
D25ViewWidget::reset ()
|
D25ViewWidget::reset ()
|
||||||
{
|
{
|
||||||
m_scale_factor = 1.0;
|
m_scale_factor = 1.0;
|
||||||
m_focus_dist = 0.0;
|
mp_mode.reset (0);
|
||||||
m_fov = 90.0;
|
|
||||||
m_cam_azimuth = m_cam_elevation = 0.0;
|
|
||||||
m_top_view = false;
|
|
||||||
m_dragging = m_rotating = false;
|
|
||||||
|
|
||||||
refresh ();
|
camera_reset ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -93,40 +229,55 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
|
||||||
double px = (event->pos ().x () - width () / 2) * 2.0 / width ();
|
double px = (event->pos ().x () - width () / 2) * 2.0 / width ();
|
||||||
double py = -(event->pos ().y () - height () / 2) * 2.0 / height ();
|
double py = -(event->pos ().y () - height () / 2) * 2.0 / height ();
|
||||||
|
|
||||||
// compute vector of line of sight
|
if (top_view ()) {
|
||||||
std::pair<QVector3D, QVector3D> ray = camera_normal (cam_perspective () * cam_trans (), px, py);
|
|
||||||
|
|
||||||
// by definition the ray goes through the camera position
|
// Plain zoom
|
||||||
QVector3D hp = hit_point_with_scene (ray.second);
|
|
||||||
|
|
||||||
if (event->modifiers () & Qt::ControlModifier) {
|
QVector3D hp (px, py, 0.0);
|
||||||
|
|
||||||
// "Ctrl" is closeup
|
|
||||||
|
|
||||||
double f = event->angleDelta ().y () * (1.0 / (90 * 8));
|
|
||||||
m_displacement += -((f / m_scale_factor) * std::min (cam_dist (), double ((cam_position () - hp).length ()))) * ray.second;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// No shift is zoom
|
|
||||||
|
|
||||||
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
|
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
|
||||||
|
|
||||||
QVector3D initial_displacement = m_displacement;
|
|
||||||
QVector3D displacement = m_displacement;
|
|
||||||
|
|
||||||
m_scale_factor *= f;
|
m_scale_factor *= f;
|
||||||
displacement += hp * (1.0 - f) / m_scale_factor;
|
m_displacement += hp * (1.0 - f) / m_scale_factor;
|
||||||
|
|
||||||
// normalize the scene translation so the scene does not "flee"
|
} else {
|
||||||
|
|
||||||
QMatrix4x4 ct = cam_trans ();
|
// compute vector of line of sight
|
||||||
initial_displacement = ct.map (initial_displacement);
|
std::pair<QVector3D, QVector3D> ray = camera_normal (cam_perspective () * cam_trans (), px, py);
|
||||||
displacement = ct.map (displacement);
|
|
||||||
|
|
||||||
lay::normalize_scene_trans (cam_perspective (), displacement, m_scale_factor, initial_displacement.z ());
|
// by definition the ray goes through the camera position
|
||||||
|
QVector3D hp = hit_point_with_scene (ray.second);
|
||||||
|
|
||||||
m_displacement = ct.inverted ().map (displacement);
|
if (event->modifiers () & Qt::ControlModifier) {
|
||||||
|
|
||||||
|
// "Ctrl" is closeup
|
||||||
|
|
||||||
|
double f = event->angleDelta ().y () * (1.0 / (90 * 8));
|
||||||
|
m_displacement += -((f / m_scale_factor) * std::min (cam_dist (), double ((cam_position () - hp).length ()))) * ray.second;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// No shift is zoom
|
||||||
|
|
||||||
|
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
|
||||||
|
|
||||||
|
QVector3D initial_displacement = m_displacement;
|
||||||
|
QVector3D displacement = m_displacement;
|
||||||
|
|
||||||
|
m_scale_factor *= f;
|
||||||
|
displacement += hp * (1.0 - f) / m_scale_factor;
|
||||||
|
|
||||||
|
// normalize the scene translation so the scene does not "flee"
|
||||||
|
|
||||||
|
QMatrix4x4 ct = cam_trans ();
|
||||||
|
initial_displacement = ct.map (initial_displacement);
|
||||||
|
displacement = ct.map (displacement);
|
||||||
|
|
||||||
|
lay::normalize_scene_trans (cam_perspective (), displacement, m_scale_factor, initial_displacement.z ());
|
||||||
|
|
||||||
|
m_displacement = ct.inverted ().map (displacement);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,10 +288,8 @@ void
|
||||||
D25ViewWidget::keyPressEvent (QKeyEvent *event)
|
D25ViewWidget::keyPressEvent (QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (event->key () == Qt::Key_Shift) {
|
if (event->key () == Qt::Key_Shift) {
|
||||||
m_top_view = true;
|
mp_mode.reset (0);
|
||||||
m_dragging = false;
|
set_top_view (true);
|
||||||
m_rotating = false;
|
|
||||||
refresh ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,10 +297,8 @@ void
|
||||||
D25ViewWidget::keyReleaseEvent (QKeyEvent *event)
|
D25ViewWidget::keyReleaseEvent (QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (event->key () == Qt::Key_Shift) {
|
if (event->key () == Qt::Key_Shift) {
|
||||||
m_top_view = false;
|
mp_mode.reset (0);
|
||||||
m_dragging = false;
|
set_top_view (false);
|
||||||
m_rotating = false;
|
|
||||||
refresh ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,181 +325,87 @@ D25ViewWidget::hit_point_with_scene (const QVector3D &line_dir)
|
||||||
void
|
void
|
||||||
D25ViewWidget::mousePressEvent (QMouseEvent *event)
|
D25ViewWidget::mousePressEvent (QMouseEvent *event)
|
||||||
{
|
{
|
||||||
m_dragging = m_rotating = false;
|
mp_mode.reset (0);
|
||||||
|
|
||||||
if (event->button () == Qt::MidButton) {
|
if (event->button () == Qt::MidButton) {
|
||||||
m_dragging = true;
|
mp_mode.reset (new D25PanInteractionMode (this, event->pos ()));
|
||||||
} else if (event->button () == Qt::LeftButton) {
|
} else if (event->button () == Qt::LeftButton) {
|
||||||
m_rotating = true;
|
if (! top_view ()) {
|
||||||
}
|
mp_mode.reset (new D25Rotate2DInteractionMode (this, event->pos ()));
|
||||||
|
} else {
|
||||||
m_start_pos = event->pos ();
|
mp_mode.reset (new D25RotateAzimuthInteractionMode (this, event->pos ()));
|
||||||
m_start_cam_position = cam_position ();
|
}
|
||||||
m_start_cam_azimuth = cam_azimuth ();
|
|
||||||
m_start_cam_elevation = cam_elevation ();
|
|
||||||
m_start_displacement = m_displacement;
|
|
||||||
|
|
||||||
m_focus_dist = 2.0;
|
|
||||||
m_hit_point = QVector3D ();
|
|
||||||
|
|
||||||
if (m_dragging) {
|
|
||||||
|
|
||||||
// by definition the ray goes through the camera position
|
|
||||||
QVector3D hp = hit_point_with_scene (cam_direction ());
|
|
||||||
|
|
||||||
m_focus_dist = (cam_position () - hp).length ();
|
|
||||||
m_hit_point = cam_position () + cam_direction () * m_focus_dist;
|
|
||||||
|
|
||||||
} else if (m_rotating) {
|
|
||||||
|
|
||||||
double px = (event->pos ().x () - width () / 2) * 2.0 / width ();
|
|
||||||
double py = -(event->pos ().y () - height () / 2) * 2.0 / height ();
|
|
||||||
|
|
||||||
// compute vector of line of sight
|
|
||||||
std::pair<QVector3D, QVector3D> ray = camera_normal (cam_perspective () * cam_trans (), px, py);
|
|
||||||
|
|
||||||
// by definition the ray goes through the camera position
|
|
||||||
QVector3D hp = hit_point_with_scene (ray.second);
|
|
||||||
|
|
||||||
m_focus_dist = std::max (m_focus_dist, double ((cam_position () - hp).length ()));
|
|
||||||
m_hit_point = cam_position () + ray.second * m_focus_dist;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
D25ViewWidget::mouseReleaseEvent (QMouseEvent * /*event*/)
|
D25ViewWidget::mouseReleaseEvent (QMouseEvent * /*event*/)
|
||||||
{
|
{
|
||||||
m_dragging = false;
|
mp_mode.reset (0);
|
||||||
m_rotating = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
D25ViewWidget::mouseMoveEvent (QMouseEvent *event)
|
D25ViewWidget::mouseMoveEvent (QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (! m_dragging && ! m_rotating) {
|
if (mp_mode.get ()) {
|
||||||
return;
|
mp_mode->mouse_move (event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_dragging) {
|
inline double square (double x) { return x * x; }
|
||||||
|
|
||||||
QPoint d = event->pos () - m_start_pos;
|
void
|
||||||
double f = tan ((cam_fov () / 2) / 180.0 * M_PI) * m_focus_dist * 2.0 / double (height ());
|
D25ViewWidget::fit ()
|
||||||
double dx = d.x () * f;
|
{
|
||||||
double dy = -d.y () * f;
|
// we pick a scale factor to adjust the z dimension roughly to 1/4 of the screen height at a focus distance of 2
|
||||||
|
double norm_height = 0.5;
|
||||||
|
double in_focus = 2.0;
|
||||||
|
m_scale_factor = (tan (cam_fov () * M_PI / 180.0 / 2.0) * 2.0) * in_focus * norm_height / std::max (0.001, (m_zmax - m_zmin));
|
||||||
|
|
||||||
QVector3D xv (cos (m_start_cam_azimuth * M_PI / 180.0), 0.0, sin (m_start_cam_azimuth * M_PI / 180.0));
|
QVector3D dim = QVector3D (m_bbox.width (), m_zmax - m_zmin, m_bbox.height ()) * m_scale_factor;
|
||||||
double re = sin (m_start_cam_elevation * M_PI / 180.0);
|
QVector3D bll = QVector3D (m_bbox.left (), m_zmin, -(m_bbox.bottom () + m_bbox.height ()));
|
||||||
QVector3D yv (-re * xv.z (), cos (m_start_cam_elevation * M_PI / 180.0), re * xv.x ());
|
|
||||||
QVector3D drag = xv * dx + yv * dy;
|
|
||||||
|
|
||||||
m_displacement = m_start_displacement + drag / m_scale_factor;
|
// now we pick a displacement which moves the center to y = 0 and x, y in a way that the dimension covers the field of
|
||||||
|
// view and is centered.
|
||||||
|
// (we use the elliptic approximation which works exactly for azimuth angles which are a multiple of 90 degree)
|
||||||
|
|
||||||
} else {
|
double dh = sqrt (square (cos (cam_azimuth () * M_PI / 180.0) * dim.x ()) + square (sin (cam_azimuth () * M_PI / 180.0) * dim.z ()));
|
||||||
|
double dv = sqrt (square (cos (cam_azimuth () * M_PI / 180.0) * dim.z ()) + square (sin (cam_azimuth () * M_PI / 180.0) * dim.x ()));
|
||||||
|
|
||||||
if (! m_top_view) {
|
double d = std::max (dh, fabs (sin (cam_elevation ()) * dv));
|
||||||
|
|
||||||
// fixed focus point for rotation
|
QVector3D new_center (0.0, 0.0, -dv / 2.0 + std::max (0.0, -d / (2.0 * tan (cam_fov () * M_PI / 180.0 / 2.0)) + cam_dist ()));
|
||||||
double focus_dist = 2.0;
|
QVector3D new_center_in_scene = cam_trans ().inverted ().map (new_center);
|
||||||
|
|
||||||
QPoint d = event->pos () - m_start_pos;
|
new_center_in_scene.setY (0.0);
|
||||||
double f = tan ((cam_fov () / 2) / 180.0 * M_PI) * focus_dist * 2.0 / double (height ());
|
|
||||||
double dx = d.x () * f;
|
|
||||||
double dy = -d.y () * f;
|
|
||||||
|
|
||||||
double da = dx / (cam_dist () - focus_dist) * 180.0 / M_PI;
|
m_displacement = (new_center_in_scene - dim * 0.5) / m_scale_factor - bll;
|
||||||
m_cam_azimuth = m_start_cam_azimuth + da;
|
|
||||||
|
|
||||||
double de = dy / (cam_dist () - focus_dist) * 180.0 / M_PI;
|
|
||||||
m_cam_elevation = m_start_cam_elevation + de;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// simple change of azimuth only - with center in the middle
|
|
||||||
|
|
||||||
QPoint m = event->pos () - m_start_pos;
|
|
||||||
QVector3D p (m_start_pos.x () - width () / 2, -m_start_pos.y () + height () / 2, 0);
|
|
||||||
QVector3D d (m.x (), -m.y (), 0);
|
|
||||||
|
|
||||||
double cp = QVector3D::crossProduct (p, p + d).z () / p.length () / (p + d).length ();
|
|
||||||
cp = std::max (-1.0, std::min (1.0, cp));
|
|
||||||
double da = asin (cp) * 180.0 / M_PI;
|
|
||||||
|
|
||||||
m_cam_azimuth += da;
|
|
||||||
m_start_pos = event->pos ();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh ();
|
refresh ();
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
|
||||||
D25ViewWidget::cam_fov () const
|
|
||||||
{
|
|
||||||
return m_fov; // @@@
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
D25ViewWidget::cam_dist () const
|
|
||||||
{
|
|
||||||
return 4.0; // @@@
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector3D
|
|
||||||
D25ViewWidget::cam_direction () const
|
|
||||||
{
|
|
||||||
QVector3D cd = cam_trans ().map (QVector3D (0, 0, 1));
|
|
||||||
cd.setZ (-cd.z ());
|
|
||||||
return cd;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector3D
|
|
||||||
D25ViewWidget::cam_position () const
|
|
||||||
{
|
|
||||||
return cam_direction () * -cam_dist ();
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
D25ViewWidget::cam_azimuth () const
|
|
||||||
{
|
|
||||||
return m_cam_azimuth;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
D25ViewWidget::cam_elevation () const
|
|
||||||
{
|
|
||||||
return m_top_view ? -90.0 : m_cam_elevation;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMatrix4x4
|
|
||||||
D25ViewWidget::cam_perspective () const
|
|
||||||
{
|
|
||||||
QMatrix4x4 t;
|
|
||||||
t.perspective (cam_fov (), float (width ()) / float (height ()), 0.1f, 10000.0f);
|
|
||||||
t.translate (QVector3D (0.0, 0.0, -cam_dist ()));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMatrix4x4
|
|
||||||
D25ViewWidget::cam_trans () const
|
|
||||||
{
|
|
||||||
QMatrix4x4 t;
|
|
||||||
t.rotate (-cam_elevation (), 1.0, 0.0, 0.0);
|
|
||||||
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
D25ViewWidget::refresh ()
|
D25ViewWidget::refresh ()
|
||||||
{
|
{
|
||||||
QVector3D cp = cam_position ();
|
QVector3D cp = cam_position ();
|
||||||
|
|
||||||
printf("@@@ e=%g a=%g x,y,z=%g,%g,%g d=%g,%g,%g s=%g f=%g\n", cam_elevation (), cam_azimuth (), cp.x(), cp.y(), cp.z(), m_displacement.x(), m_displacement.y(), m_displacement.z(), m_scale_factor, m_focus_dist); fflush(stdout);
|
printf("@@@ e=%g a=%g x,y,z=%g,%g,%g d=%g,%g,%g s=%g\n", cam_elevation (), cam_azimuth (), cp.x(), cp.y(), cp.z(), m_displacement.x(), m_displacement.y(), m_displacement.z(), m_scale_factor); fflush(stdout);
|
||||||
|
|
||||||
update ();
|
update ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
D25ViewWidget::camera_changed ()
|
||||||
|
{
|
||||||
|
refresh ();
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
D25ViewWidget::aspect_ratio () const
|
||||||
|
{
|
||||||
|
return double (width ()) / double (height ());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
D25ViewWidget::attach_view (LayoutView *view)
|
D25ViewWidget::attach_view (LayoutView *view)
|
||||||
{
|
{
|
||||||
|
|
@ -439,61 +492,26 @@ D25ViewWidget::render_polygon (D25ViewWidget::chunks_type &chunks, const db::Pol
|
||||||
|
|
||||||
// triangle bottom
|
// triangle bottom
|
||||||
|
|
||||||
chunks.add (pts[0].x () * dbu);
|
chunks.add (pts[0].x () * dbu, zstart, pts[0].y () * dbu);
|
||||||
chunks.add (zstart);
|
chunks.add (pts[2].x () * dbu, zstart, pts[2].y () * dbu);
|
||||||
chunks.add (pts[0].y () * dbu);
|
chunks.add (pts[1].x () * dbu, zstart, pts[1].y () * dbu);
|
||||||
|
|
||||||
chunks.add (pts[2].x () * dbu);
|
|
||||||
chunks.add (zstart);
|
|
||||||
chunks.add (pts[2].y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (pts[1].x () * dbu);
|
|
||||||
chunks.add (zstart);
|
|
||||||
chunks.add (pts[1].y () * dbu);
|
|
||||||
|
|
||||||
// triangle top
|
// triangle top
|
||||||
|
chunks.add (pts[0].x () * dbu, zstop, pts[0].y () * dbu);
|
||||||
chunks.add (pts[0].x () * dbu);
|
chunks.add (pts[1].x () * dbu, zstop, pts[1].y () * dbu);
|
||||||
chunks.add (zstop);
|
chunks.add (pts[2].x () * dbu, zstop, pts[2].y () * dbu);
|
||||||
chunks.add (pts[0].y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (pts[1].x () * dbu);
|
|
||||||
chunks.add (zstop);
|
|
||||||
chunks.add (pts[1].y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (pts[2].x () * dbu);
|
|
||||||
chunks.add (zstop);
|
|
||||||
chunks.add (pts[2].y () * dbu);
|
|
||||||
|
|
||||||
if (poly.hull ().size () == 4) {
|
if (poly.hull ().size () == 4) {
|
||||||
|
|
||||||
// triangle bottom
|
// triangle bottom
|
||||||
|
chunks.add (pts[0].x () * dbu, zstart, pts[0].y () * dbu);
|
||||||
chunks.add (pts[0].x () * dbu);
|
chunks.add (pts[3].x () * dbu, zstart, pts[3].y () * dbu);
|
||||||
chunks.add (zstart);
|
chunks.add (pts[2].x () * dbu, zstart, pts[2].y () * dbu);
|
||||||
chunks.add (pts[0].y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (pts[3].x () * dbu);
|
|
||||||
chunks.add (zstart);
|
|
||||||
chunks.add (pts[3].y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (pts[2].x () * dbu);
|
|
||||||
chunks.add (zstart);
|
|
||||||
chunks.add (pts[2].y () * dbu);
|
|
||||||
|
|
||||||
// triangle top
|
// triangle top
|
||||||
|
chunks.add (pts[0].x () * dbu, zstop, pts[0].y () * dbu);
|
||||||
chunks.add (pts[0].x () * dbu);
|
chunks.add (pts[2].x () * dbu, zstop, pts[2].y () * dbu);
|
||||||
chunks.add (zstop);
|
chunks.add (pts[3].x () * dbu, zstop, pts[3].y () * dbu);
|
||||||
chunks.add (pts[0].y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (pts[2].x () * dbu);
|
|
||||||
chunks.add (zstop);
|
|
||||||
chunks.add (pts[2].y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (pts[3].x () * dbu);
|
|
||||||
chunks.add (zstop);
|
|
||||||
chunks.add (pts[3].y () * dbu);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -503,29 +521,12 @@ D25ViewWidget::render_polygon (D25ViewWidget::chunks_type &chunks, const db::Pol
|
||||||
void
|
void
|
||||||
D25ViewWidget::render_wall (D25ViewWidget::chunks_type &chunks, const db::Edge &edge, double dbu, double zstart, double zstop)
|
D25ViewWidget::render_wall (D25ViewWidget::chunks_type &chunks, const db::Edge &edge, double dbu, double zstart, double zstop)
|
||||||
{
|
{
|
||||||
chunks.add (edge.p1 ().x () * dbu);
|
chunks.add (edge.p1 ().x () * dbu, zstart, edge.p1 ().y () * dbu);
|
||||||
chunks.add (zstart);
|
chunks.add (edge.p2 ().x () * dbu, zstop, edge.p2 ().y () * dbu);
|
||||||
chunks.add (edge.p1 ().y () * dbu);
|
chunks.add (edge.p1 ().x () * dbu, zstop, edge.p1 ().y () * dbu);
|
||||||
|
chunks.add (edge.p1 ().x () * dbu, zstart, edge.p1 ().y () * dbu);
|
||||||
chunks.add (edge.p2 ().x () * dbu);
|
chunks.add (edge.p2 ().x () * dbu, zstart, edge.p2 ().y () * dbu);
|
||||||
chunks.add (zstop);
|
chunks.add (edge.p2 ().x () * dbu, zstop, edge.p2 ().y () * dbu);
|
||||||
chunks.add (edge.p2 ().y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (edge.p1 ().x () * dbu);
|
|
||||||
chunks.add (zstop);
|
|
||||||
chunks.add (edge.p1 ().y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (edge.p1 ().x () * dbu);
|
|
||||||
chunks.add (zstart);
|
|
||||||
chunks.add (edge.p1 ().y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (edge.p2 ().x () * dbu);
|
|
||||||
chunks.add (zstart);
|
|
||||||
chunks.add (edge.p2 ().y () * dbu);
|
|
||||||
|
|
||||||
chunks.add (edge.p2 ().x () * dbu);
|
|
||||||
chunks.add (zstop);
|
|
||||||
chunks.add (edge.p2 ().y () * dbu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -642,8 +643,7 @@ D25ViewWidget::initializeGL ()
|
||||||
"uniform vec4 ambient;\n"
|
"uniform vec4 ambient;\n"
|
||||||
"uniform vec3 illum;\n"
|
"uniform vec3 illum;\n"
|
||||||
"out lowp vec4 vertexColor;\n"
|
"out lowp vec4 vertexColor;\n"
|
||||||
"uniform mat4 geo_matrix;\n"
|
"uniform mat4 matrix;\n"
|
||||||
"uniform mat4 cam_matrix;\n"
|
|
||||||
"layout (triangles) in;\n"
|
"layout (triangles) in;\n"
|
||||||
"layout (triangle_strip, max_vertices = 3) out;\n"
|
"layout (triangle_strip, max_vertices = 3) out;\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -655,11 +655,11 @@ D25ViewWidget::initializeGL ()
|
||||||
" float dp = dot(normalize(n), illum);\n"
|
" float dp = dot(normalize(n), illum);\n"
|
||||||
" vertexColor = color * (dp * 0.5 + 0.5) - (min(0.0, dp) * 0.5 * ambient);\n"
|
" vertexColor = color * (dp * 0.5 + 0.5) - (min(0.0, dp) * 0.5 * ambient);\n"
|
||||||
" vertexColor.a = 1.0;\n"
|
" vertexColor.a = 1.0;\n"
|
||||||
" gl_Position = cam_matrix * geo_matrix * p0;\n"
|
" gl_Position = matrix * p0;\n"
|
||||||
" EmitVertex();\n"
|
" EmitVertex();\n"
|
||||||
" gl_Position = cam_matrix * geo_matrix * p1;\n"
|
" gl_Position = matrix * p1;\n"
|
||||||
" EmitVertex();\n"
|
" EmitVertex();\n"
|
||||||
" gl_Position = cam_matrix * geo_matrix * p2;\n"
|
" gl_Position = matrix * p2;\n"
|
||||||
" EmitVertex();\n"
|
" EmitVertex();\n"
|
||||||
" EndPrimitive();\n"
|
" EndPrimitive();\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
@ -743,9 +743,6 @@ D25ViewWidget::initializeGL ()
|
||||||
void
|
void
|
||||||
D25ViewWidget::paintGL ()
|
D25ViewWidget::paintGL ()
|
||||||
{
|
{
|
||||||
GLfloat vertices[6000];
|
|
||||||
size_t nmax = sizeof (vertices) / sizeof (GLfloat);
|
|
||||||
|
|
||||||
const qreal retinaScale = devicePixelRatio ();
|
const qreal retinaScale = devicePixelRatio ();
|
||||||
glViewport (0, 0, width () * retinaScale, height () * retinaScale);
|
glViewport (0, 0, width () * retinaScale, height () * retinaScale);
|
||||||
|
|
||||||
|
|
@ -767,8 +764,9 @@ D25ViewWidget::paintGL ()
|
||||||
|
|
||||||
m_shapes_program->bind ();
|
m_shapes_program->bind ();
|
||||||
|
|
||||||
m_shapes_program->setUniformValue ("geo_matrix", cam_trans () * scene_trans);
|
// draw the actual layout
|
||||||
m_shapes_program->setUniformValue ("cam_matrix", cam_perspective ());
|
|
||||||
|
m_shapes_program->setUniformValue ("matrix", cam_perspective () * cam_trans () * scene_trans);
|
||||||
|
|
||||||
// NOTE: z axis of illum points towards the scene because we include the z inversion in the scene transformation matrix
|
// NOTE: z axis of illum points towards the scene because we include the z inversion in the scene transformation matrix
|
||||||
m_shapes_program->setUniformValue ("illum", QVector3D (-3.0, -4.0, 2.0).normalized ());
|
m_shapes_program->setUniformValue ("illum", QVector3D (-3.0, -4.0, 2.0).normalized ());
|
||||||
|
|
@ -779,20 +777,19 @@ D25ViewWidget::paintGL ()
|
||||||
glEnableVertexAttribArray (positions);
|
glEnableVertexAttribArray (positions);
|
||||||
|
|
||||||
for (std::list<LayerInfo>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
for (std::list<LayerInfo>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
||||||
|
|
||||||
m_shapes_program->setUniformValue ("color", l->color [0], l->color [1], l->color [2], l->color [3]);
|
m_shapes_program->setUniformValue ("color", l->color [0], l->color [1], l->color [2], l->color [3]);
|
||||||
|
l->vertex_chunk->draw_to (this, positions, GL_TRIANGLES);
|
||||||
for (chunks_type::iterator c = l->vertex_chunk->begin (); c != l->vertex_chunk->end (); ++c) {
|
|
||||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, c->front ());
|
|
||||||
glDrawArrays (GL_TRIANGLES, 0, c->size () / 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glDisableVertexAttribArray (positions);
|
glDisableVertexAttribArray (positions);
|
||||||
|
|
||||||
m_shapes_program->release ();
|
m_shapes_program->release ();
|
||||||
|
|
||||||
|
// decoration
|
||||||
|
|
||||||
|
// a vertex buffer for the decoration
|
||||||
|
lay::mem_chunks<float, 1024 * 18> vertexes;
|
||||||
|
|
||||||
m_gridplane_program->bind ();
|
m_gridplane_program->bind ();
|
||||||
|
|
||||||
glEnable (GL_DEPTH_TEST);
|
glEnable (GL_DEPTH_TEST);
|
||||||
|
|
@ -802,26 +799,14 @@ D25ViewWidget::paintGL ()
|
||||||
|
|
||||||
m_gridplane_program->setUniformValue ("matrix", cam_perspective () * cam_trans ());
|
m_gridplane_program->setUniformValue ("matrix", cam_perspective () * cam_trans ());
|
||||||
|
|
||||||
size_t index = 0;
|
|
||||||
|
|
||||||
double compass_rad = 0.3;
|
double compass_rad = 0.3;
|
||||||
double compass_bars = 0.4;
|
double compass_bars = 0.4;
|
||||||
|
|
||||||
vertices[index++] = -compass_bars;
|
vertexes.add (-compass_bars, 0.0, 0.0);
|
||||||
vertices[index++] = 0.0;
|
vertexes.add (compass_bars, 0.0, 0.0);
|
||||||
vertices[index++] = 0.0;
|
|
||||||
|
|
||||||
vertices[index++] = compass_bars;
|
vertexes.add (0.0, 0.0, -compass_bars);
|
||||||
vertices[index++] = 0.0;
|
vertexes.add (0.0, 0.0, compass_bars);
|
||||||
vertices[index++] = 0.0;
|
|
||||||
|
|
||||||
vertices[index++] = 0.0;
|
|
||||||
vertices[index++] = 0.0;
|
|
||||||
vertices[index++] = -compass_bars;
|
|
||||||
|
|
||||||
vertices[index++] = 0.0;
|
|
||||||
vertices[index++] = 0.0;
|
|
||||||
vertices[index++] = compass_bars;
|
|
||||||
|
|
||||||
int ncircle = 64;
|
int ncircle = 64;
|
||||||
double x = compass_rad, z = 0.0;
|
double x = compass_rad, z = 0.0;
|
||||||
|
|
@ -833,13 +818,8 @@ D25ViewWidget::paintGL ()
|
||||||
double xx = compass_rad * cos (a);
|
double xx = compass_rad * cos (a);
|
||||||
double zz = compass_rad * sin (a);
|
double zz = compass_rad * sin (a);
|
||||||
|
|
||||||
vertices[index++] = x;
|
vertexes.add (x, 0.0, z);
|
||||||
vertices[index++] = 0.0;
|
vertexes.add (xx, 0.0, zz);
|
||||||
vertices[index++] = z;
|
|
||||||
|
|
||||||
vertices[index++] = xx;
|
|
||||||
vertices[index++] = 0.0;
|
|
||||||
vertices[index++] = zz;
|
|
||||||
|
|
||||||
x = xx;
|
x = xx;
|
||||||
z = zz;
|
z = zz;
|
||||||
|
|
@ -848,29 +828,18 @@ D25ViewWidget::paintGL ()
|
||||||
|
|
||||||
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, 0.25f);
|
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, 0.25f);
|
||||||
|
|
||||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, vertices);
|
|
||||||
|
|
||||||
glLineWidth (2.0);
|
glLineWidth (2.0);
|
||||||
glDrawArrays (GL_LINES, 0, index / 3);
|
vertexes.draw_to (this, positions, GL_LINES);
|
||||||
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
// arrow
|
// arrow
|
||||||
vertices[index++] = -0.25 * compass_rad;
|
|
||||||
vertices[index++] = 0.0;
|
|
||||||
vertices[index++] = 0.6 * compass_rad;
|
|
||||||
|
|
||||||
vertices[index++] = 0.0;
|
vertexes.clear ();
|
||||||
vertices[index++] = 0.0;
|
|
||||||
vertices[index++] = -0.8 * compass_rad;
|
|
||||||
|
|
||||||
vertices[index++] = 0.25 * compass_rad;
|
vertexes.add (-0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||||
vertices[index++] = 0.0;
|
vertexes.add (0.0, 0.0, -0.8 * compass_rad);
|
||||||
vertices[index++] = 0.6 * compass_rad;
|
vertexes.add (0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||||
|
|
||||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, vertices);
|
vertexes.draw_to (this, positions, GL_TRIANGLES);
|
||||||
|
|
||||||
glDrawArrays (GL_TRIANGLES, 0, index / 3);
|
|
||||||
|
|
||||||
// draw base plane
|
// draw base plane
|
||||||
|
|
||||||
|
|
@ -880,71 +849,61 @@ D25ViewWidget::paintGL ()
|
||||||
double gminor = gg.second, gmajor = gg.first;
|
double gminor = gg.second, gmajor = gg.first;
|
||||||
|
|
||||||
double margin = std::max (m_bbox.width (), m_bbox.height ()) * 0.02;
|
double margin = std::max (m_bbox.width (), m_bbox.height ()) * 0.02;
|
||||||
double l = m_bbox.left () - margin;
|
|
||||||
double r = m_bbox.right () + margin;
|
|
||||||
double b = m_bbox.bottom () - margin;
|
|
||||||
double t = m_bbox.top () + margin;
|
|
||||||
|
|
||||||
// @@@
|
double l = m_bbox.left ();
|
||||||
|
double r = m_bbox.right ();
|
||||||
|
double b = m_bbox.bottom ();
|
||||||
|
double t = m_bbox.top ();
|
||||||
|
|
||||||
// major and minor grid lines
|
// major and minor grid lines
|
||||||
|
|
||||||
|
vertexes.clear ();
|
||||||
|
|
||||||
const double epsilon = 1e-6;
|
const double epsilon = 1e-6;
|
||||||
|
|
||||||
for (int major = 0; major < 2; ++major) {
|
for (int major = 0; major < 2; ++major) {
|
||||||
|
|
||||||
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, major ? 0.25f : 0.15f);
|
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, major ? 0.25f : 0.15f);
|
||||||
|
|
||||||
size_t index = 0;
|
|
||||||
double x, y;
|
double x, y;
|
||||||
double step = (major ? gmajor : gminor);
|
double step = (major ? gmajor : gminor);
|
||||||
|
|
||||||
x = ceil (l / step) * step;
|
x = ceil (l / step) * step;
|
||||||
for ( ; index < nmax && x < r - step * epsilon; x += step) {
|
for ( ; x < r - step * epsilon; x += step) {
|
||||||
if ((fabs (floor (x / gmajor + 0.5) * gmajor - x) < epsilon) == (major != 0)) {
|
if ((fabs (floor (x / gmajor + 0.5) * gmajor - x) < epsilon) == (major != 0)) {
|
||||||
vertices [index++] = x;
|
vertexes.add (x, 0.0, b - margin);
|
||||||
vertices [index++] = 0.0;
|
vertexes.add (x, 0.0, t + margin);
|
||||||
vertices [index++] = b;
|
|
||||||
vertices [index++] = x;
|
|
||||||
vertices [index++] = 0.0;
|
|
||||||
vertices [index++] = t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y = ceil (b / step) * step;
|
y = ceil (b / step) * step;
|
||||||
for ( ; index < nmax && y < t - step * epsilon; y += step) {
|
for ( ; y < t - step * epsilon; y += step) {
|
||||||
if ((fabs (floor (y / gmajor + 0.5) * gmajor - y) < epsilon) == (major != 0)) {
|
if ((fabs (floor (y / gmajor + 0.5) * gmajor - y) < epsilon) == (major != 0)) {
|
||||||
vertices [index++] = l;
|
vertexes.add (l - margin, 0.0, y);
|
||||||
vertices [index++] = 0.0;
|
vertexes.add (r + margin, 0.0, y);
|
||||||
vertices [index++] = y;
|
|
||||||
vertices [index++] = r;
|
|
||||||
vertices [index++] = 0.0;
|
|
||||||
vertices [index++] = y;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, vertices);
|
|
||||||
|
|
||||||
glLineWidth (2.0);
|
glLineWidth (2.0);
|
||||||
glDrawArrays (GL_LINES, 0, index / 3);
|
vertexes.draw_to (this, positions, GL_LINES);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l = m_bbox.left ();
|
// the plane itself
|
||||||
r = m_bbox.right ();
|
|
||||||
b = m_bbox.bottom ();
|
|
||||||
t = m_bbox.top ();
|
|
||||||
|
|
||||||
GLfloat plane_vertices[] = {
|
vertexes.clear ();
|
||||||
float (l), 0.0f, float (b), float (l), 0.0f, float (t), float (r), 0.0f, float (t),
|
|
||||||
float (l), 0.0f, float (b), float (r), 0.0f, float (t), float (r), 0.0f, float (b)
|
vertexes.add (l, 0.0, b);
|
||||||
};
|
vertexes.add (l, 0.0, t);
|
||||||
|
vertexes.add (r, 0.0, t);
|
||||||
|
|
||||||
|
vertexes.add (l, 0.0, b);
|
||||||
|
vertexes.add (r, 0.0, b);
|
||||||
|
vertexes.add (r, 0.0, t);
|
||||||
|
|
||||||
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, 0.1f);
|
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, 0.1f);
|
||||||
|
|
||||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, plane_vertices);
|
vertexes.draw_to (this, positions, GL_TRIANGLES);
|
||||||
|
|
||||||
glDrawArrays (GL_TRIANGLES, 0, 6);
|
|
||||||
|
|
||||||
glDisableVertexAttribArray (positions);
|
glDisableVertexAttribArray (positions);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@
|
||||||
#ifndef HDR_layD25ViewWidget
|
#ifndef HDR_layD25ViewWidget
|
||||||
#define HDR_layD25ViewWidget
|
#define HDR_layD25ViewWidget
|
||||||
|
|
||||||
|
#include "dbPolygon.h"
|
||||||
|
|
||||||
|
#include "layD25MemChunks.h"
|
||||||
|
#include "layD25Camera.h"
|
||||||
|
|
||||||
#include <QOpenGLWidget>
|
#include <QOpenGLWidget>
|
||||||
#include <QOpenGLVertexArrayObject>
|
#include <QOpenGLVertexArrayObject>
|
||||||
#include <QOpenGLBuffer>
|
#include <QOpenGLBuffer>
|
||||||
|
|
@ -32,9 +37,7 @@
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
#include <QVector3D>
|
#include <QVector3D>
|
||||||
|
|
||||||
#include "dbPolygon.h"
|
#include <memory>
|
||||||
|
|
||||||
#include "layD25MemChunks.h"
|
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
@ -46,10 +49,25 @@ namespace lay
|
||||||
{
|
{
|
||||||
|
|
||||||
class LayoutView;
|
class LayoutView;
|
||||||
|
class D25ViewWidget;
|
||||||
|
|
||||||
|
class D25InteractionMode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
D25InteractionMode (D25ViewWidget *widget);
|
||||||
|
virtual ~D25InteractionMode ();
|
||||||
|
|
||||||
|
D25ViewWidget *view () { return mp_view; }
|
||||||
|
virtual void mouse_move (QMouseEvent *event) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
D25ViewWidget *mp_view;
|
||||||
|
};
|
||||||
|
|
||||||
class D25ViewWidget
|
class D25ViewWidget
|
||||||
: public QOpenGLWidget,
|
: public QOpenGLWidget,
|
||||||
private QOpenGLFunctions
|
private QOpenGLFunctions,
|
||||||
|
public D25Camera
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
@ -66,22 +84,40 @@ public:
|
||||||
|
|
||||||
void attach_view (lay::LayoutView *view);
|
void attach_view (lay::LayoutView *view);
|
||||||
|
|
||||||
|
QVector3D hit_point_with_scene(const QVector3D &line_dir);
|
||||||
|
void refresh ();
|
||||||
|
void reset ();
|
||||||
|
|
||||||
|
QVector3D displacement () const { return m_displacement; }
|
||||||
|
|
||||||
|
void set_displacement (const QVector3D &d)
|
||||||
|
{
|
||||||
|
m_displacement = d;
|
||||||
|
refresh ();
|
||||||
|
}
|
||||||
|
|
||||||
|
double scale_factor () const { return m_scale_factor; }
|
||||||
|
|
||||||
|
void set_scale_factor (double f)
|
||||||
|
{
|
||||||
|
m_scale_factor = f;
|
||||||
|
refresh ();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void camera_changed ();
|
||||||
|
virtual double aspect_ratio () const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void fit ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef lay::mem_chunks<GLfloat, 1024 * 9> chunks_type;
|
typedef lay::mem_chunks<GLfloat, 1024 * 9> chunks_type;
|
||||||
|
|
||||||
|
std::auto_ptr<D25InteractionMode> mp_mode;
|
||||||
QOpenGLShaderProgram *m_shapes_program, *m_gridplane_program;
|
QOpenGLShaderProgram *m_shapes_program, *m_gridplane_program;
|
||||||
bool m_dragging, m_rotating;
|
|
||||||
double m_scale_factor;
|
double m_scale_factor;
|
||||||
double m_cam_azimuth, m_cam_elevation;
|
|
||||||
bool m_top_view;
|
|
||||||
QVector3D m_displacement;
|
QVector3D m_displacement;
|
||||||
double m_focus_dist;
|
|
||||||
double m_fov;
|
|
||||||
QVector3D m_hit_point;
|
|
||||||
QPoint m_start_pos;
|
|
||||||
QVector3D m_start_cam_position;
|
|
||||||
double m_start_cam_azimuth, m_start_cam_elevation;
|
|
||||||
QVector3D m_start_displacement;
|
|
||||||
lay::LayoutView *mp_view;
|
lay::LayoutView *mp_view;
|
||||||
db::DBox m_bbox;
|
db::DBox m_bbox;
|
||||||
double m_zmin, m_zmax;
|
double m_zmin, m_zmax;
|
||||||
|
|
@ -99,21 +135,10 @@ private:
|
||||||
void paintGL ();
|
void paintGL ();
|
||||||
void resizeGL (int w, int h);
|
void resizeGL (int w, int h);
|
||||||
|
|
||||||
void refresh ();
|
|
||||||
void reset ();
|
|
||||||
void prepare_view ();
|
void prepare_view ();
|
||||||
void render_layout (D25ViewWidget::chunks_type &chunks, const db::Layout &layout, const db::Cell &cell, unsigned int layer, double zstart, double zstop);
|
void render_layout (D25ViewWidget::chunks_type &chunks, const db::Layout &layout, const db::Cell &cell, unsigned int layer, double zstart, double zstop);
|
||||||
void render_polygon (D25ViewWidget::chunks_type &chunks, const db::Polygon &poly, double dbu, double zstart, double zstop);
|
void render_polygon (D25ViewWidget::chunks_type &chunks, const db::Polygon &poly, double dbu, double zstart, double zstop);
|
||||||
void render_wall (D25ViewWidget::chunks_type &chunks, const db::Edge &poly, double dbu, double zstart, double zstop);
|
void render_wall (D25ViewWidget::chunks_type &chunks, const db::Edge &poly, double dbu, double zstart, double zstop);
|
||||||
QVector3D hit_point_with_scene(const QVector3D &line_dir);
|
|
||||||
double cam_elevation () const;
|
|
||||||
double cam_azimuth () const;
|
|
||||||
QVector3D cam_position () const;
|
|
||||||
QVector3D cam_direction () const;
|
|
||||||
QMatrix4x4 cam_perspective () const;
|
|
||||||
QMatrix4x4 cam_trans () const;
|
|
||||||
double cam_dist () const;
|
|
||||||
double cam_fov () const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,16 @@ HEADERS = \
|
||||||
layD25View.h \
|
layD25View.h \
|
||||||
layD25ViewWidget.h \
|
layD25ViewWidget.h \
|
||||||
layD25MemChunks.h \
|
layD25MemChunks.h \
|
||||||
layD25ViewUtils.h
|
layD25ViewUtils.h \
|
||||||
|
layD25Camera.h
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
layD25View.cc \
|
layD25View.cc \
|
||||||
layD25ViewWidget.cc \
|
layD25ViewWidget.cc \
|
||||||
layD25Plugin.cc \
|
layD25Plugin.cc \
|
||||||
layD25MemChunks.cc \
|
layD25MemChunks.cc \
|
||||||
layD25ViewUtils.cc
|
layD25ViewUtils.cc \
|
||||||
|
layD25Camera.cc
|
||||||
|
|
||||||
FORMS = \
|
FORMS = \
|
||||||
D25View.ui \
|
D25View.ui \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "layD25Camera.h"
|
||||||
|
#include "tlUnitTest.h"
|
||||||
|
|
||||||
|
static std::string v2s (const QVector4D &v)
|
||||||
|
{
|
||||||
|
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ()) + "," + tl::to_string (v.z ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string v2s (const QVector3D &v)
|
||||||
|
{
|
||||||
|
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ()) + "," + tl::to_string (v.z ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string v2s_2d (const QVector3D &v)
|
||||||
|
{
|
||||||
|
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(1_Transformations)
|
||||||
|
{
|
||||||
|
lay::D25Camera cam;
|
||||||
|
|
||||||
|
cam.set_cam_azimuth (45.0);
|
||||||
|
EXPECT_EQ (cam.cam_azimuth (), 45.0);
|
||||||
|
cam.set_cam_elevation (22.0);
|
||||||
|
EXPECT_EQ (cam.cam_elevation (), 22.0);
|
||||||
|
|
||||||
|
cam.camera_reset ();
|
||||||
|
EXPECT_EQ (cam.cam_azimuth (), 0.0);
|
||||||
|
EXPECT_EQ (cam.cam_elevation (), 0.0);
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "1,0,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,1,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "0,0,1");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_direction ()), "0,0,-1");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_position ()), "0,0,4");
|
||||||
|
|
||||||
|
// looking up from the bottom, x axis stays the same (azimuth = 0)
|
||||||
|
cam.set_cam_elevation (90.0);
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "1,0,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,0,-1");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "0,1,0");
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_direction ()), "0,1,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_position ()), "0,-4,0");
|
||||||
|
|
||||||
|
// looking down from the top, x axis stays the same (azimuth = 0)
|
||||||
|
cam.set_cam_elevation (-90.0);
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "1,0,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,0,1");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "0,-1,0");
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_direction ()), "0,-1,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_position ()), "0,4,0");
|
||||||
|
|
||||||
|
// looking from the left, y axis stays the same (elevation = 0)
|
||||||
|
cam.set_cam_elevation (0.0);
|
||||||
|
cam.set_cam_azimuth (90.0);
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "0,0,-1");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,1,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "1,0,0");
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_direction ()), "1,0,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_position ()), "-4,0,0");
|
||||||
|
|
||||||
|
// looking from the right, y axis stays the same (elevation = 0)
|
||||||
|
cam.set_cam_elevation (0.0);
|
||||||
|
cam.set_cam_azimuth (-90.0);
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "0,0,1");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,1,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "-1,0,0");
|
||||||
|
|
||||||
|
EXPECT_EQ (v2s (cam.cam_direction ()), "-1,0,0");
|
||||||
|
EXPECT_EQ (v2s (cam.cam_position ()), "4,0,0");
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,8 @@ include($$PWD/../../../../lib_ut.pri)
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
layD25MemChunksTests.cc \
|
layD25MemChunksTests.cc \
|
||||||
layD25ViewUtilsTests.cc
|
layD25ViewUtilsTests.cc \
|
||||||
|
layD25CameraTests.cc
|
||||||
|
|
||||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../lay_plugin $$PWD/../../../common
|
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../lay_plugin $$PWD/../../../common
|
||||||
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../lay_plugin $$PWD/../../../common
|
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../lay_plugin $$PWD/../../../common
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue