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="file_12.png">images/file_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 prefix="/syntax">
|
||||
<file alias="ruby.xml">syntax/ruby.xml</file>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>576</width>
|
||||
<height>649</height>
|
||||
<width>854</width>
|
||||
<height>665</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -29,17 +29,249 @@
|
|||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</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>
|
||||
<widget class="lay::D25ViewWidget" name="d25_view"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</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>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
@ -51,10 +283,9 @@
|
|||
<header>layD25ViewWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../../../../lay/lay/layResources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<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"
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#define HDR_layD25MemChunks
|
||||
|
||||
#include <QDialog>
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
#include "tlObject.h"
|
||||
#include <string.h> // for memcpy
|
||||
|
|
@ -31,6 +32,19 @@
|
|||
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
|
||||
*
|
||||
|
|
@ -201,6 +215,25 @@ public:
|
|||
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
|
||||
*/
|
||||
|
|
@ -211,6 +244,17 @@ public:
|
|||
*/
|
||||
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:
|
||||
chunk *mp_chunks;
|
||||
chunk *mp_last_chunk;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
namespace lay
|
||||
{
|
||||
|
||||
const double initial_elevation = 3.0;
|
||||
|
||||
D25View::D25View (QWidget *parent)
|
||||
: QDialog (parent)
|
||||
{
|
||||
|
|
@ -41,6 +43,13 @@ D25View::D25View (QWidget *parent)
|
|||
mp_ui->d25_view->setFocusPolicy (Qt::StrongFocus);
|
||||
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 ()
|
||||
|
|
@ -55,6 +64,10 @@ D25View::exec_dialog (lay::LayoutView *view)
|
|||
mp_view.reset (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 ();
|
||||
|
||||
mp_ui->d25_view->attach_view (0);
|
||||
|
|
@ -62,6 +75,36 @@ D25View::exec_dialog (lay::LayoutView *view)
|
|||
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
|
||||
D25View::accept ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ public:
|
|||
protected:
|
||||
void accept ();
|
||||
|
||||
private slots:
|
||||
void fit_button_clicked ();
|
||||
|
||||
private:
|
||||
Ui::D25View *mp_ui;
|
||||
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)
|
||||
{
|
||||
// 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 ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
: QOpenGLWidget (parent),
|
||||
m_shapes_program (0)
|
||||
|
|
@ -74,13 +214,9 @@ void
|
|||
D25ViewWidget::reset ()
|
||||
{
|
||||
m_scale_factor = 1.0;
|
||||
m_focus_dist = 0.0;
|
||||
m_fov = 90.0;
|
||||
m_cam_azimuth = m_cam_elevation = 0.0;
|
||||
m_top_view = false;
|
||||
m_dragging = m_rotating = false;
|
||||
mp_mode.reset (0);
|
||||
|
||||
refresh ();
|
||||
camera_reset ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -93,40 +229,55 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
|
|||
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);
|
||||
if (top_view ()) {
|
||||
|
||||
// by definition the ray goes through the camera position
|
||||
QVector3D hp = hit_point_with_scene (ray.second);
|
||||
// Plain zoom
|
||||
|
||||
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
|
||||
QVector3D hp (px, py, 0.0);
|
||||
|
||||
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;
|
||||
m_displacement += hp * (1.0 - f) / m_scale_factor;
|
||||
|
||||
// normalize the scene translation so the scene does not "flee"
|
||||
} else {
|
||||
|
||||
QMatrix4x4 ct = cam_trans ();
|
||||
initial_displacement = ct.map (initial_displacement);
|
||||
displacement = ct.map (displacement);
|
||||
// compute vector of line of sight
|
||||
std::pair<QVector3D, QVector3D> ray = camera_normal (cam_perspective () * cam_trans (), px, py);
|
||||
|
||||
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)
|
||||
{
|
||||
if (event->key () == Qt::Key_Shift) {
|
||||
m_top_view = true;
|
||||
m_dragging = false;
|
||||
m_rotating = false;
|
||||
refresh ();
|
||||
mp_mode.reset (0);
|
||||
set_top_view (true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,10 +297,8 @@ void
|
|||
D25ViewWidget::keyReleaseEvent (QKeyEvent *event)
|
||||
{
|
||||
if (event->key () == Qt::Key_Shift) {
|
||||
m_top_view = false;
|
||||
m_dragging = false;
|
||||
m_rotating = false;
|
||||
refresh ();
|
||||
mp_mode.reset (0);
|
||||
set_top_view (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,181 +325,87 @@ D25ViewWidget::hit_point_with_scene (const QVector3D &line_dir)
|
|||
void
|
||||
D25ViewWidget::mousePressEvent (QMouseEvent *event)
|
||||
{
|
||||
m_dragging = m_rotating = false;
|
||||
mp_mode.reset (0);
|
||||
|
||||
if (event->button () == Qt::MidButton) {
|
||||
m_dragging = true;
|
||||
mp_mode.reset (new D25PanInteractionMode (this, event->pos ()));
|
||||
} else if (event->button () == Qt::LeftButton) {
|
||||
m_rotating = true;
|
||||
}
|
||||
|
||||
m_start_pos = 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;
|
||||
|
||||
if (! top_view ()) {
|
||||
mp_mode.reset (new D25Rotate2DInteractionMode (this, event->pos ()));
|
||||
} else {
|
||||
mp_mode.reset (new D25RotateAzimuthInteractionMode (this, event->pos ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
D25ViewWidget::mouseReleaseEvent (QMouseEvent * /*event*/)
|
||||
{
|
||||
m_dragging = false;
|
||||
m_rotating = false;
|
||||
mp_mode.reset (0);
|
||||
}
|
||||
|
||||
void
|
||||
D25ViewWidget::mouseMoveEvent (QMouseEvent *event)
|
||||
{
|
||||
if (! m_dragging && ! m_rotating) {
|
||||
return;
|
||||
if (mp_mode.get ()) {
|
||||
mp_mode->mouse_move (event);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_dragging) {
|
||||
inline double square (double x) { return x * x; }
|
||||
|
||||
QPoint d = event->pos () - m_start_pos;
|
||||
double f = tan ((cam_fov () / 2) / 180.0 * M_PI) * m_focus_dist * 2.0 / double (height ());
|
||||
double dx = d.x () * f;
|
||||
double dy = -d.y () * f;
|
||||
void
|
||||
D25ViewWidget::fit ()
|
||||
{
|
||||
// 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));
|
||||
double re = sin (m_start_cam_elevation * M_PI / 180.0);
|
||||
QVector3D yv (-re * xv.z (), cos (m_start_cam_elevation * M_PI / 180.0), re * xv.x ());
|
||||
QVector3D drag = xv * dx + yv * dy;
|
||||
QVector3D dim = QVector3D (m_bbox.width (), m_zmax - m_zmin, m_bbox.height ()) * m_scale_factor;
|
||||
QVector3D bll = QVector3D (m_bbox.left (), m_zmin, -(m_bbox.bottom () + m_bbox.height ()));
|
||||
|
||||
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
|
||||
double focus_dist = 2.0;
|
||||
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 ()));
|
||||
QVector3D new_center_in_scene = cam_trans ().inverted ().map (new_center);
|
||||
|
||||
QPoint d = event->pos () - m_start_pos;
|
||||
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;
|
||||
new_center_in_scene.setY (0.0);
|
||||
|
||||
double da = dx / (cam_dist () - focus_dist) * 180.0 / M_PI;
|
||||
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 ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
m_displacement = (new_center_in_scene - dim * 0.5) / m_scale_factor - bll;
|
||||
|
||||
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
|
||||
D25ViewWidget::refresh ()
|
||||
{
|
||||
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 ();
|
||||
}
|
||||
|
||||
void
|
||||
D25ViewWidget::camera_changed ()
|
||||
{
|
||||
refresh ();
|
||||
}
|
||||
|
||||
double
|
||||
D25ViewWidget::aspect_ratio () const
|
||||
{
|
||||
return double (width ()) / double (height ());
|
||||
}
|
||||
|
||||
void
|
||||
D25ViewWidget::attach_view (LayoutView *view)
|
||||
{
|
||||
|
|
@ -439,61 +492,26 @@ D25ViewWidget::render_polygon (D25ViewWidget::chunks_type &chunks, const db::Pol
|
|||
|
||||
// triangle bottom
|
||||
|
||||
chunks.add (pts[0].x () * dbu);
|
||||
chunks.add (zstart);
|
||||
chunks.add (pts[0].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);
|
||||
chunks.add (pts[0].x () * dbu, zstart, pts[0].y () * dbu);
|
||||
chunks.add (pts[2].x () * dbu, zstart, pts[2].y () * dbu);
|
||||
chunks.add (pts[1].x () * dbu, zstart, pts[1].y () * dbu);
|
||||
|
||||
// triangle top
|
||||
|
||||
chunks.add (pts[0].x () * dbu);
|
||||
chunks.add (zstop);
|
||||
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);
|
||||
chunks.add (pts[0].x () * dbu, zstop, pts[0].y () * dbu);
|
||||
chunks.add (pts[1].x () * dbu, zstop, pts[1].y () * dbu);
|
||||
chunks.add (pts[2].x () * dbu, zstop, pts[2].y () * dbu);
|
||||
|
||||
if (poly.hull ().size () == 4) {
|
||||
|
||||
// triangle bottom
|
||||
|
||||
chunks.add (pts[0].x () * dbu);
|
||||
chunks.add (zstart);
|
||||
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);
|
||||
chunks.add (pts[0].x () * dbu, zstart, pts[0].y () * dbu);
|
||||
chunks.add (pts[3].x () * dbu, zstart, pts[3].y () * dbu);
|
||||
chunks.add (pts[2].x () * dbu, zstart, pts[2].y () * dbu);
|
||||
|
||||
// triangle top
|
||||
|
||||
chunks.add (pts[0].x () * dbu);
|
||||
chunks.add (zstop);
|
||||
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);
|
||||
chunks.add (pts[0].x () * dbu, zstop, pts[0].y () * dbu);
|
||||
chunks.add (pts[2].x () * dbu, zstop, pts[2].y () * dbu);
|
||||
chunks.add (pts[3].x () * dbu, zstop, pts[3].y () * dbu);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -503,29 +521,12 @@ D25ViewWidget::render_polygon (D25ViewWidget::chunks_type &chunks, const db::Pol
|
|||
void
|
||||
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 (zstart);
|
||||
chunks.add (edge.p1 ().y () * dbu);
|
||||
|
||||
chunks.add (edge.p2 ().x () * dbu);
|
||||
chunks.add (zstop);
|
||||
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);
|
||||
chunks.add (edge.p1 ().x () * dbu, zstart, edge.p1 ().y () * dbu);
|
||||
chunks.add (edge.p2 ().x () * dbu, zstop, edge.p2 ().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, zstart, edge.p2 ().y () * dbu);
|
||||
chunks.add (edge.p2 ().x () * dbu, zstop, edge.p2 ().y () * dbu);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -642,8 +643,7 @@ D25ViewWidget::initializeGL ()
|
|||
"uniform vec4 ambient;\n"
|
||||
"uniform vec3 illum;\n"
|
||||
"out lowp vec4 vertexColor;\n"
|
||||
"uniform mat4 geo_matrix;\n"
|
||||
"uniform mat4 cam_matrix;\n"
|
||||
"uniform mat4 matrix;\n"
|
||||
"layout (triangles) in;\n"
|
||||
"layout (triangle_strip, max_vertices = 3) out;\n"
|
||||
"\n"
|
||||
|
|
@ -655,11 +655,11 @@ D25ViewWidget::initializeGL ()
|
|||
" float dp = dot(normalize(n), illum);\n"
|
||||
" vertexColor = color * (dp * 0.5 + 0.5) - (min(0.0, dp) * 0.5 * ambient);\n"
|
||||
" vertexColor.a = 1.0;\n"
|
||||
" gl_Position = cam_matrix * geo_matrix * p0;\n"
|
||||
" gl_Position = matrix * p0;\n"
|
||||
" EmitVertex();\n"
|
||||
" gl_Position = cam_matrix * geo_matrix * p1;\n"
|
||||
" gl_Position = matrix * p1;\n"
|
||||
" EmitVertex();\n"
|
||||
" gl_Position = cam_matrix * geo_matrix * p2;\n"
|
||||
" gl_Position = matrix * p2;\n"
|
||||
" EmitVertex();\n"
|
||||
" EndPrimitive();\n"
|
||||
"}\n";
|
||||
|
|
@ -743,9 +743,6 @@ D25ViewWidget::initializeGL ()
|
|||
void
|
||||
D25ViewWidget::paintGL ()
|
||||
{
|
||||
GLfloat vertices[6000];
|
||||
size_t nmax = sizeof (vertices) / sizeof (GLfloat);
|
||||
|
||||
const qreal retinaScale = devicePixelRatio ();
|
||||
glViewport (0, 0, width () * retinaScale, height () * retinaScale);
|
||||
|
||||
|
|
@ -767,8 +764,9 @@ D25ViewWidget::paintGL ()
|
|||
|
||||
m_shapes_program->bind ();
|
||||
|
||||
m_shapes_program->setUniformValue ("geo_matrix", cam_trans () * scene_trans);
|
||||
m_shapes_program->setUniformValue ("cam_matrix", cam_perspective ());
|
||||
// draw the actual layout
|
||||
|
||||
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
|
||||
m_shapes_program->setUniformValue ("illum", QVector3D (-3.0, -4.0, 2.0).normalized ());
|
||||
|
|
@ -779,20 +777,19 @@ D25ViewWidget::paintGL ()
|
|||
glEnableVertexAttribArray (positions);
|
||||
|
||||
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]);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
l->vertex_chunk->draw_to (this, positions, GL_TRIANGLES);
|
||||
}
|
||||
|
||||
glDisableVertexAttribArray (positions);
|
||||
|
||||
m_shapes_program->release ();
|
||||
|
||||
// decoration
|
||||
|
||||
// a vertex buffer for the decoration
|
||||
lay::mem_chunks<float, 1024 * 18> vertexes;
|
||||
|
||||
m_gridplane_program->bind ();
|
||||
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
|
|
@ -802,26 +799,14 @@ D25ViewWidget::paintGL ()
|
|||
|
||||
m_gridplane_program->setUniformValue ("matrix", cam_perspective () * cam_trans ());
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
double compass_rad = 0.3;
|
||||
double compass_bars = 0.4;
|
||||
|
||||
vertices[index++] = -compass_bars;
|
||||
vertices[index++] = 0.0;
|
||||
vertices[index++] = 0.0;
|
||||
vertexes.add (-compass_bars, 0.0, 0.0);
|
||||
vertexes.add (compass_bars, 0.0, 0.0);
|
||||
|
||||
vertices[index++] = compass_bars;
|
||||
vertices[index++] = 0.0;
|
||||
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;
|
||||
vertexes.add (0.0, 0.0, -compass_bars);
|
||||
vertexes.add (0.0, 0.0, compass_bars);
|
||||
|
||||
int ncircle = 64;
|
||||
double x = compass_rad, z = 0.0;
|
||||
|
|
@ -833,13 +818,8 @@ D25ViewWidget::paintGL ()
|
|||
double xx = compass_rad * cos (a);
|
||||
double zz = compass_rad * sin (a);
|
||||
|
||||
vertices[index++] = x;
|
||||
vertices[index++] = 0.0;
|
||||
vertices[index++] = z;
|
||||
|
||||
vertices[index++] = xx;
|
||||
vertices[index++] = 0.0;
|
||||
vertices[index++] = zz;
|
||||
vertexes.add (x, 0.0, z);
|
||||
vertexes.add (xx, 0.0, zz);
|
||||
|
||||
x = xx;
|
||||
z = zz;
|
||||
|
|
@ -848,29 +828,18 @@ D25ViewWidget::paintGL ()
|
|||
|
||||
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);
|
||||
glDrawArrays (GL_LINES, 0, index / 3);
|
||||
|
||||
index = 0;
|
||||
vertexes.draw_to (this, positions, GL_LINES);
|
||||
|
||||
// arrow
|
||||
vertices[index++] = -0.25 * compass_rad;
|
||||
vertices[index++] = 0.0;
|
||||
vertices[index++] = 0.6 * compass_rad;
|
||||
|
||||
vertices[index++] = 0.0;
|
||||
vertices[index++] = 0.0;
|
||||
vertices[index++] = -0.8 * compass_rad;
|
||||
vertexes.clear ();
|
||||
|
||||
vertices[index++] = 0.25 * compass_rad;
|
||||
vertices[index++] = 0.0;
|
||||
vertices[index++] = 0.6 * compass_rad;
|
||||
vertexes.add (-0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||
vertexes.add (0.0, 0.0, -0.8 * compass_rad);
|
||||
vertexes.add (0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||
|
||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||
|
||||
glDrawArrays (GL_TRIANGLES, 0, index / 3);
|
||||
vertexes.draw_to (this, positions, GL_TRIANGLES);
|
||||
|
||||
// draw base plane
|
||||
|
||||
|
|
@ -880,71 +849,61 @@ D25ViewWidget::paintGL ()
|
|||
double gminor = gg.second, gmajor = gg.first;
|
||||
|
||||
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
|
||||
|
||||
vertexes.clear ();
|
||||
|
||||
const double epsilon = 1e-6;
|
||||
|
||||
for (int major = 0; major < 2; ++major) {
|
||||
|
||||
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, major ? 0.25f : 0.15f);
|
||||
|
||||
size_t index = 0;
|
||||
double x, y;
|
||||
double step = (major ? gmajor : gminor);
|
||||
|
||||
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)) {
|
||||
vertices [index++] = x;
|
||||
vertices [index++] = 0.0;
|
||||
vertices [index++] = b;
|
||||
vertices [index++] = x;
|
||||
vertices [index++] = 0.0;
|
||||
vertices [index++] = t;
|
||||
vertexes.add (x, 0.0, b - margin);
|
||||
vertexes.add (x, 0.0, t + margin);
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
vertices [index++] = l;
|
||||
vertices [index++] = 0.0;
|
||||
vertices [index++] = y;
|
||||
vertices [index++] = r;
|
||||
vertices [index++] = 0.0;
|
||||
vertices [index++] = y;
|
||||
vertexes.add (l - margin, 0.0, y);
|
||||
vertexes.add (r + margin, 0.0, y);
|
||||
}
|
||||
}
|
||||
|
||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||
|
||||
glLineWidth (2.0);
|
||||
glDrawArrays (GL_LINES, 0, index / 3);
|
||||
vertexes.draw_to (this, positions, GL_LINES);
|
||||
|
||||
}
|
||||
|
||||
l = m_bbox.left ();
|
||||
r = m_bbox.right ();
|
||||
b = m_bbox.bottom ();
|
||||
t = m_bbox.top ();
|
||||
// the plane itself
|
||||
|
||||
GLfloat plane_vertices[] = {
|
||||
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.clear ();
|
||||
|
||||
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);
|
||||
|
||||
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, plane_vertices);
|
||||
|
||||
glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||
vertexes.draw_to (this, positions, GL_TRIANGLES);
|
||||
|
||||
glDisableVertexAttribArray (positions);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@
|
|||
#ifndef HDR_layD25ViewWidget
|
||||
#define HDR_layD25ViewWidget
|
||||
|
||||
#include "dbPolygon.h"
|
||||
|
||||
#include "layD25MemChunks.h"
|
||||
#include "layD25Camera.h"
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
#include <QOpenGLBuffer>
|
||||
|
|
@ -32,9 +37,7 @@
|
|||
#include <QPoint>
|
||||
#include <QVector3D>
|
||||
|
||||
#include "dbPolygon.h"
|
||||
|
||||
#include "layD25MemChunks.h"
|
||||
#include <memory>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -46,10 +49,25 @@ namespace lay
|
|||
{
|
||||
|
||||
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
|
||||
: public QOpenGLWidget,
|
||||
private QOpenGLFunctions
|
||||
private QOpenGLFunctions,
|
||||
public D25Camera
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -66,22 +84,40 @@ public:
|
|||
|
||||
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:
|
||||
typedef lay::mem_chunks<GLfloat, 1024 * 9> chunks_type;
|
||||
|
||||
std::auto_ptr<D25InteractionMode> mp_mode;
|
||||
QOpenGLShaderProgram *m_shapes_program, *m_gridplane_program;
|
||||
bool m_dragging, m_rotating;
|
||||
double m_scale_factor;
|
||||
double m_cam_azimuth, m_cam_elevation;
|
||||
bool m_top_view;
|
||||
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;
|
||||
db::DBox m_bbox;
|
||||
double m_zmin, m_zmax;
|
||||
|
|
@ -99,21 +135,10 @@ private:
|
|||
void paintGL ();
|
||||
void resizeGL (int w, int h);
|
||||
|
||||
void refresh ();
|
||||
void reset ();
|
||||
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_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);
|
||||
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 \
|
||||
layD25ViewWidget.h \
|
||||
layD25MemChunks.h \
|
||||
layD25ViewUtils.h
|
||||
layD25ViewUtils.h \
|
||||
layD25Camera.h
|
||||
|
||||
SOURCES = \
|
||||
layD25View.cc \
|
||||
layD25ViewWidget.cc \
|
||||
layD25Plugin.cc \
|
||||
layD25MemChunks.cc \
|
||||
layD25ViewUtils.cc
|
||||
layD25ViewUtils.cc \
|
||||
layD25Camera.cc
|
||||
|
||||
FORMS = \
|
||||
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 = \
|
||||
layD25MemChunksTests.cc \
|
||||
layD25ViewUtilsTests.cc
|
||||
layD25ViewUtilsTests.cc \
|
||||
layD25CameraTests.cc
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue