This commit is contained in:
Matthias Koefferlein 2020-04-11 22:46:35 +02:00
parent 56d406aaad
commit 7077bac647
7 changed files with 527 additions and 23 deletions

View File

@ -0,0 +1,164 @@
/*
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 "layD25ViewUtils.h"
#include <QMatrix4x4>
#include <QMatrix3x3>
#include <math.h>
namespace lay
{
const double epsilon = 1e-10;
std::pair<bool, QVector3D>
cutpoint_line_with_plane (const QVector3D &line, const QVector3D &dir, const QVector3D &plane, const QVector3D &plane_normal)
{
double dn = QVector3D::dotProduct (dir, plane_normal);
if (fabs (dn) < epsilon) {
return std::make_pair (false, QVector3D ());
} else {
return std::make_pair (true, line + dir * QVector3D::dotProduct (plane - line, plane_normal) / dn);
}
}
std::pair<bool, QVector3D>
cutpoint_line_with_face (const QVector3D &line, const QVector3D &dir, const QVector3D &plane, const QVector3D &u, const QVector3D &v)
{
QVector3D n = QVector3D::crossProduct (u, v);
std::pair<bool, QVector3D> r = cutpoint_line_with_plane (line, dir, plane, n);
if (! r.first) {
return r;
}
double pu = QVector3D::dotProduct (r.second - plane, u);
double pv = QVector3D::dotProduct (r.second - plane, v);
// test whether the cut point is inside the face
if (pu < -epsilon || pu > u.lengthSquared () + epsilon || pv < -epsilon || pv > v.lengthSquared () + epsilon) {
return std::make_pair (false, QVector3D ());
} else {
return r;
}
}
static std::pair<bool, QVector3D> plane_or_face (const QVector3D &line, const QVector3D &line_dir, const QVector3D &corner, const QVector3D &u, const QVector3D &v, bool face)
{
if (face) {
return cutpoint_line_with_face (line, line_dir, corner, u, v);
} else {
return cutpoint_line_with_plane (line, line_dir, corner, QVector3D::crossProduct (u, v));
}
}
std::pair<bool, QVector3D>
hit_point_with_cuboid (const QVector3D &line, const QVector3D &line_dir, const QVector3D &corner, const QVector3D &dim)
{
std::vector<std::pair<bool, QVector3D> > cutpoints;
cutpoints.reserve (6); // 6 faces
for (int pass = 0; pass < 2; ++pass) {
bool face = (pass == 0);
if (face) {
bool in_x = (line.x () > corner.x () - epsilon) && (line.x () < corner.x () + dim.x () + epsilon);
bool in_y = (line.y () > corner.y () - epsilon) && (line.y () < corner.y () + dim.y () + epsilon);
bool in_z = (line.z () > corner.z () - epsilon) && (line.z () < corner.z () + dim.z () + epsilon);
if (in_x && in_y && in_z) {
// inside cuboid
return std::make_pair (true, line);
}
}
cutpoints.clear ();
// front
cutpoints.push_back (plane_or_face (line, line_dir, corner, QVector3D (dim.x (), 0, 0), QVector3D (0, dim.y (), 0), face));
// back
cutpoints.push_back (plane_or_face (line, line_dir, corner + QVector3D (0, 0, dim.z ()), QVector3D (dim.x (), 0, 0), QVector3D (0, dim.y (), 0), face));
if (face) {
// bottom
cutpoints.push_back (plane_or_face (line, line_dir, corner, QVector3D (dim.x (), 0, 0), QVector3D (0, 0, dim.z ()), face));
// top
cutpoints.push_back (plane_or_face (line, line_dir, corner + QVector3D (0, dim.y (), 0), QVector3D (dim.x (), 0, 0), QVector3D (0, 0, dim.z ()), face));
// left
cutpoints.push_back (plane_or_face (line, line_dir, corner, QVector3D (0, 0, dim.z ()), QVector3D (0, dim.y (), 0), face));
// right
cutpoints.push_back (plane_or_face (line, line_dir, corner + QVector3D (dim.x (), 0, 0), QVector3D (0, 0, dim.z ()), QVector3D (0, dim.y (), 0), face));
}
double min_dist = 0.0;
int min_dist_index = -1;
QVector3D ld_norm = line_dir.normalized ();
for (std::vector<std::pair<bool, QVector3D> >::const_iterator i = cutpoints.begin (); i != cutpoints.end (); ++i) {
if (i->first) {
double dist = QVector3D::dotProduct (i->second - line, ld_norm);
if (dist < -epsilon) {
// ignore all cutpoints behind us
} else if (min_dist_index < 0) {
min_dist = dist;
min_dist_index = int (i - cutpoints.begin ());
} else if (dist < min_dist) {
min_dist = dist;
min_dist_index = int (i - cutpoints.begin ());
}
}
}
if (min_dist_index >= 0) {
return cutpoints [min_dist_index];
}
}
return std::make_pair (false, QVector3D ());
}
std::pair<QVector3D, QVector3D>
camera_normal (const QMatrix4x4 &camera_trans, double x, double y)
{
QVector3D p = camera_trans.inverted ().map (QVector3D (x, y, 1.0));
QVector4D pv = camera_trans.row (3);
QMatrix4x4 m (camera_trans);
float values[] = {
float (x * pv.x ()), float (x * pv.y ()), float (x * pv.z ()), 0.0f,
float (y * pv.x ()), float (y * pv.y ()), float (y * pv.z ()), 0.0f,
float (pv.x ()), float (pv.y ()), float (pv.z ()), 0.0f,
0.0f, 0.0f, 0.0f, 0.0f
};
m -= QMatrix4x4 (values);
QMatrix3x3 nm = m.normalMatrix ();
QVector3D u (nm (2, 0), nm (2, 1), nm (2, 2));
return (std::make_pair (p, u.normalized ()));
}
}

View File

@ -0,0 +1,80 @@
/*
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_layD25ViewUtils
#define HDR_layD25ViewUtils
#include "layPluginCommon.h"
#include <QVector3D>
#include <QMatrix4x4>
#include <algorithm>
namespace lay
{
/**
* @brief Computes the cutpoint between a line and a plane
*
* The line is given by a point and a direction (line, line_dir).
* The plane is given by a point and a normal vector (plane, plane_normal)
* The "first" component of the returned pair is false if not hit is present.
*/
LAY_PLUGIN_PUBLIC std::pair<bool, QVector3D>
cutpoint_line_with_plane (const QVector3D &line, const QVector3D &line_dir, const QVector3D &plane, const QVector3D &plane_normal);
/**
* @brief Computes the cutpoint between a line and a face
*
* The line is given by a point and a direction (line, line_dir).
* The face is given by a plane point and two vectors spanning the face.
* The "first" component of the returned pair is false if not hit is present.
*/
LAY_PLUGIN_PUBLIC std::pair<bool, QVector3D>
cutpoint_line_with_face (const QVector3D &line, const QVector3D &dir, const QVector3D &plane, const QVector3D &u, const QVector3D &v);
/**
* @brief Determines a good hit point of a view line and a cuboid
*
* "corner, dim" are the coordinates for the cuboid (corner is the bottom, left, foremost corner, dim
* is (width, height, depth)
* "line, line_dir" is the view line where "line_dir" is pointing from the camera to the object.
* The returned point is a suitable hit point.
* The "first" component of the returned pair is false if no hit is present.
*/
LAY_PLUGIN_PUBLIC std::pair<bool, QVector3D>
hit_point_with_cuboid (const QVector3D &line, const QVector3D &line_dir, const QVector3D &corner, const QVector3D &dim);
/**
* @brief For a given pixel coordinate and camera transformation matrix compute a line containing all points corresponding to this pixel
*
* The returned pair contains a point and a direction vector describing the line.
*/
LAY_PLUGIN_PUBLIC std::pair<QVector3D, QVector3D>
camera_normal (const QMatrix4x4 &camera_trans, double x, double y);
}
#endif

View File

@ -22,6 +22,7 @@
#include "layD25ViewWidget.h"
#include "layD25ViewUtils.h"
#include "layLayoutView.h"
#include "dbRecursiveShapeIterator.h"
@ -50,7 +51,9 @@ D25ViewWidget::D25ViewWidget (QWidget *parent)
format.setSamples (4); // more -> widget extends beyond boundary!
setFormat (format);
m_cam_position = QVector3D (0.0, 0.0, 3.0); // @@@
m_cam_position = QVector3D (0.0, 0.0, 4.0); // @@@
m_scale_factor = 1.0;
m_focus_dist = 0.0;
}
D25ViewWidget::~D25ViewWidget ()
@ -194,19 +197,36 @@ static QVector3D cam_direction (double azimuth, double elevation)
void
D25ViewWidget::wheelEvent (QWheelEvent *event)
{
double cal = 0.6;
double px = (event->pos ().x () - width () / 2) * 2.0 / width ();
double py = -(event->pos ().y () - height () / 2) * 2.0 / height ();
int dx = event->pos ().x () - width () / 2;
int dy = -(event->pos ().y () - height () / 2);
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
double da = atan (dx * cal * 2.0 / height ()) * 180 / M_PI;
double de = atan (dy * cal * 2.0 / height ()) * 180 / M_PI;
// compute vector of line of sight
std::pair<QVector3D, QVector3D> ray = camera_normal (m_cam_trans, px, py);
m_cam_position += (event->angleDelta ().y () * (1.0 / (45 * 8))) * cam_direction (m_cam_azimuth + da, m_cam_elevation + de);
// by definition the ray goes through the camera position
std::pair<bool, QVector3D> hp = hit_point_with_scene (m_cam_position, ray.second);
QVector3D pm = m_cam_trans.map(hp.second);
printf("@@@ mouse=%g,%g back=%g,%g\n", px, py, pm.x(), pm.y());
printf("@@@ before: hp=%g,%g,%g d=%g,%g,%g s=%g\n", hp.second.x(), hp.second.y(), hp.second.z(), m_displacement.x(), m_displacement.y(), m_displacement.z(), m_scale_factor); fflush(stdout);
m_displacement = hp.second * (1.0 - f) + m_displacement * f;
m_scale_factor *= f;
update_cam_trans ();
}
std::pair<bool, QVector3D>
D25ViewWidget::hit_point_with_scene (const QVector3D &line, const QVector3D &line_dir)
{
QVector3D corner = QVector3D (m_bbox.left (), m_zmin, -(m_bbox.bottom () + m_bbox.height ())) * m_scale_factor + m_displacement;
QVector3D dim = QVector3D (m_bbox.width (), m_zmax - m_zmin, m_bbox.height ()) * m_scale_factor;
return lay::hit_point_with_cuboid (line, line_dir, corner, dim);
}
void
D25ViewWidget::mousePressEvent (QMouseEvent *event)
{
@ -221,6 +241,19 @@ D25ViewWidget::mousePressEvent (QMouseEvent *event)
m_start_cam_position = m_cam_position;
m_start_cam_azimuth = m_cam_azimuth;
m_start_cam_elevation = m_cam_elevation;
m_start_displacement = m_displacement;
m_focus_dist = 2.0;
if (m_dragging || m_rotating) {
QVector3D cd = cam_direction (m_start_cam_azimuth, m_start_cam_elevation);
std::pair<bool, QVector3D> hp = hit_point_with_scene (m_cam_position, cd);
if (hp.first) {
m_focus_dist = std::max (m_focus_dist, double ((m_cam_position - hp.second).length ()));
}
}
}
void
@ -232,12 +265,10 @@ D25ViewWidget::mouseReleaseEvent (QMouseEvent * /*event*/)
void
D25ViewWidget::mouseMoveEvent (QMouseEvent *event)
{
double focus_dist = 4.0; // 4 times focal length
if (m_dragging) {
// for the chosen perspective transformation:
double cal = 0.6 * focus_dist;
double cal = 0.6 * m_focus_dist;
QPoint d = event->pos () - m_start_pos;
double f = cal * 2.0 / double (height ());
@ -249,13 +280,14 @@ D25ViewWidget::mouseMoveEvent (QMouseEvent *event)
QVector3D yv (-re * xv.z (), cos (m_start_cam_elevation * M_PI / 180.0), re * xv.x ());
QVector3D drag = xv * dx + yv * dy;
// "-drag" because we're not dragging the camera, we're dragging the scene
m_cam_position = m_start_cam_position - drag;
m_displacement = m_start_displacement + drag;
update_cam_trans ();
} else if (m_rotating) {
double focus_dist = 4.0; // @@@
QPoint d = event->pos () - m_start_pos;
double ax = atan (d.x () / (0.5 * height ())) * 180 / M_PI;
@ -274,9 +306,12 @@ D25ViewWidget::mouseMoveEvent (QMouseEvent *event)
void
D25ViewWidget::update_cam_trans ()
{
printf("@@@ e=%g a=%g x,y,z=%g,%g,%g\n", m_cam_elevation, m_cam_azimuth, m_cam_position.x(), m_cam_position.y(), m_cam_position.z()); fflush(stdout);
printf("@@@ e=%g a=%g x,y,z=%g,%g,%g d=%g,%g,%g s=%g f=%g\n", m_cam_elevation, m_cam_azimuth, m_cam_position.x(), m_cam_position.y(), m_cam_position.z(), m_displacement.x(), m_displacement.y(), m_displacement.z(), m_scale_factor, m_focus_dist); fflush(stdout);
QMatrix4x4 t;
// finally add perspective
t.perspective (60.0f, float (width ()) / float (height ()), 0.1f, 100.0f);
// third: elevation
t.rotate (-m_cam_elevation, 1.0, 0.0, 0.0);
@ -312,6 +347,10 @@ D25ViewWidget::prepare_view ()
{
double z = 0.0, dz = 0.2; // @@@
m_bbox = db::DBox ();
bool zset = false;
m_zmin = m_zmax = 0.0;
for (lay::LayerPropertiesConstIterator lp = mp_view->begin_layers (); ! lp.at_end (); ++lp) {
if (! lp->has_children () && lp->visible (true) && lp->cellview_index () >= 0 && lp->cellview_index () < int (mp_view->cellviews ())) {
@ -322,9 +361,9 @@ D25ViewWidget::prepare_view ()
LayerInfo info;
// @@@ use alpha?
info.color[0] = (color & 0xff) / 255.0f;
info.color[0] = ((color >> 16) & 0xff) / 255.0f;
info.color[1] = ((color >> 8) & 0xff) / 255.0f;
info.color[2] = ((color >> 16) & 0xff) / 255.0f;
info.color[2] = (color & 0xff) / 255.0f;
info.color[3] = 1.0;
info.vertex_chunk = &m_vertex_chunks.back ();
@ -333,6 +372,17 @@ D25ViewWidget::prepare_view ()
const lay::CellView &cv = mp_view->cellview ((unsigned int) lp->cellview_index ());
render_layout (m_vertex_chunks.back (), cv->layout (), *cv.cell (), (unsigned int) lp->layer_index (), z, z + dz);
m_bbox += db::DBox (cv.cell ()->bbox ((unsigned int) lp->layer_index ())) * cv->layout ().dbu ();
if (! zset) {
m_zmin = z;
m_zmax = z + dz;
zset = true;
} else {
m_zmin = std::min (z, m_zmin);
m_zmax = std::max (z + dz, m_zmax);
}
z += dz; // @@@
}
@ -513,6 +563,7 @@ D25ViewWidget::render_layout (D25ViewWidget::chunks_type &chunks, const db::Layo
void
D25ViewWidget::paintGL ()
{
printf("@@@ width=%d,height=%d\n", width(),height()); // @@@
const qreal retinaScale = devicePixelRatio ();
glViewport (0, 0, width () * retinaScale, height () * retinaScale);
@ -523,12 +574,19 @@ D25ViewWidget::paintGL ()
m_shapes_program->bind ();
QMatrix4x4 matrix;
matrix.perspective (60.0f, float (width ()) / float (height ()), 0.1f, 100.0f);
matrix *= m_cam_trans;
QMatrix4x4 scene_trans;
// provide the displacement and scaling
scene_trans.translate (m_displacement);
scene_trans.scale (m_scale_factor);
// this way we can use y as z coordinate when drawing
scene_trans.scale (1.0, 1.0, -1.0);
m_shapes_program->setUniformValue ("matrix", m_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 ());
m_shapes_program->setUniformValue ("matrix", matrix);
m_shapes_program->setUniformValue ("illum", QVector3D (-3.0, -4.0, -2.0).normalized ());
m_shapes_program->setUniformValue ("ambient", QVector4D (0.5, 0.5, 0.5, 0.5));
glEnableVertexAttribArray (positions);
@ -552,7 +610,8 @@ D25ViewWidget::paintGL ()
glEnableVertexAttribArray (positions);
m_gridplane_program->setUniformValue ("matrix", matrix);
// @@@ m_gridplane_program->setUniformValue ("matrix", m_cam_trans * m_scene_trans);
m_gridplane_program->setUniformValue ("matrix", QMatrix4x4 ()); // @@@
// @@@
@ -567,6 +626,7 @@ D25ViewWidget::paintGL ()
glDrawArrays (GL_TRIANGLES, 0, 6);
#if 0
GLfloat gridline_vertices[] = {
-1.0, 0.0, -2.0, -1.0, 0.0, 0.0,
-0.75, 0.0, -2.0, -0.75, 0.0, 0.0,
@ -587,6 +647,28 @@ D25ViewWidget::paintGL ()
1.0, 0.0, -0.25, -1.0, 0.0, -0.25,
1.0, 0.0, 0.0, -1.0, 0.0, 0.0
};
#else
GLfloat gridline_vertices[] = {
-1.0, -1.0, 0.0, -1.0, 1.0, 0.0,
-0.75, -1.0, 0.0, -0.75, 1.0, 0.0,
-0.5, -1.0, 0.0, -0.5, 1.0, 0.0,
-0.25, -1.0, 0.0, -0.25, 1.0, 0.0,
0.0, -1.0, 0.0, 0.0, 1.0, 0.0,
0.25, -1.0, 0.0, 0.25, 1.0, 0.0,
0.5, -1.0, 0.0, 0.5, 1.0, 0.0,
0.75, -1.0, 0.0, 0.75, 1.0, 0.0,
1.0, -1.0, 0.0, 1.0, 1.0, 0.0,
1.0, -1.0, 0.0, -1.0, -1.0, 0.0,
1.0, -0.75, 0.0, -1.0, -0.75, 0.0,
1.0, -0.5, 0.0, -1.0, -0.5, 0.0,
1.0, -0.25, 0.0, -1.0, -0.25, 0.0,
1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
1.0, 0.25, 0.0, -1.0, 0.25, 0.0,
1.0, 0.5, 0.0, -1.0, 0.5, 0.0,
1.0, 0.75, 0.0, -1.0, 0.75, 0.0,
1.0, 1.0, 0.0, -1.0, 1.0, 0.0
};
#endif
m_shapes_program->setUniformValue ("vertexColor", 1.0, 1.0, 1.0, 0.2f);

View File

@ -71,11 +71,17 @@ private:
QMatrix4x4 m_cam_trans;
bool m_dragging, m_rotating;
QVector3D m_cam_position;
double m_scale_factor;
double m_cam_azimuth, m_cam_elevation;
QVector3D m_displacement;
double m_focus_dist;
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;
std::list<chunks_type> m_vertex_chunks;
@ -95,6 +101,7 @@ private:
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);
std::pair<bool, QVector3D> hit_point_with_scene (const QVector3D &line, const QVector3D &line_dir);
};
}

View File

@ -11,13 +11,15 @@ LIBS += -L$$DESTDIR/.. -lklayout_rdb -lklayout_ant
HEADERS = \
layD25View.h \
layD25ViewWidget.h \
layD25MemChunks.h
layD25MemChunks.h \
layD25ViewUtils.h
SOURCES = \
layD25View.cc \
layD25ViewWidget.cc \
layD25Plugin.cc \
layD25MemChunks.cc
layD25MemChunks.cc \
layD25ViewUtils.cc
FORMS = \
D25View.ui \

View File

@ -0,0 +1,168 @@
/*
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 "layD25ViewUtils.h"
#include "tlUnitTest.h"
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_CutPoint)
{
std::pair<bool, QVector3D> r;
r = lay::cutpoint_line_with_plane (QVector3D (0, 0, 0), QVector3D (0, 0, 1), QVector3D (0, 0, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_plane (QVector3D (1, 2, 3), QVector3D (0, 0, 2), QVector3D (4, 5, 6), QVector3D (0, 0, 1));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,2,6");
r = lay::cutpoint_line_with_plane (QVector3D (1, 2, 3), QVector3D (0, 0, -1), QVector3D (4, 5, 6), QVector3D (1, 1, 1));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,2,12");
}
TEST(2_Face)
{
std::pair<bool, QVector3D> r;
r = lay::cutpoint_line_with_face (QVector3D (0, 0, 0), QVector3D (0, 0, 1), QVector3D (0, 0, 0), QVector3D (0, 1, 0), QVector3D (0, 0, 1));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_face (QVector3D (1, 2, 3), QVector3D (0, 0, 2), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_face (QVector3D (4, 5, 3), QVector3D (0, 0, 3), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "4,5,6");
r = lay::cutpoint_line_with_face (QVector3D (4, 7, 3), QVector3D (0, 0, 1), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_face (QVector3D (4, 6, 3), QVector3D (0, 0, 2), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "4,6,6");
r = lay::cutpoint_line_with_face (QVector3D (5, 6, 3), QVector3D (0, 0, -1), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "5,6,6");
r = lay::cutpoint_line_with_face (QVector3D (6, 6, 3), QVector3D (0, 0, 1), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
}
TEST(3_HitWithCuboid)
{
std::pair<bool, QVector3D> r;
r = lay::hit_point_with_cuboid (QVector3D (0, 0, 0), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "0,0,3");
r = lay::hit_point_with_cuboid (QVector3D (1, 1, 4), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,1,4");
r = lay::hit_point_with_cuboid (QVector3D (1, 1, 6), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, false);
r = lay::hit_point_with_cuboid (QVector3D (5, -6, 0), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "5,-6,3");
r = lay::hit_point_with_cuboid (QVector3D (5, -6, 4), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "5,-6,5");
r = lay::hit_point_with_cuboid (QVector3D (5, -6, 6), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, false);
}
TEST(4_CameraNormal)
{
QMatrix4x4 matrix;
matrix.perspective (60.0f, 1.5, 0.1f, 100.0f);
std::pair<QVector3D, QVector3D> ray;
QVector3D p;
ray = lay::camera_normal (matrix, 0.0, 0.0);
EXPECT_EQ (v2s (ray.second.normalized ()), "0,0,-1");
ray = lay::camera_normal (matrix, 1.0, 0.0);
EXPECT_EQ (v2s (ray.second), "0.654654,0,-0.755929");
p = matrix.map (ray.first);
EXPECT_EQ (v2s_2d (p), "1,0");
p = matrix.map (ray.first + ray.second);
EXPECT_EQ (v2s_2d (p), "1,0");
p = matrix.map (ray.first + ray.second * 1000.0);
EXPECT_EQ (v2s_2d (p), "1,0");
ray = lay::camera_normal (matrix, 0.0, -1.0);
EXPECT_EQ (v2s (ray.second), "0,-0.5,-0.866025");
p = matrix.map (ray.first);
EXPECT_EQ (v2s_2d (p), "0,-1");
p = matrix.map (ray.first + ray.second);
EXPECT_EQ (v2s_2d (p), "0,-1");
p = matrix.map (ray.first + ray.second * 1000.0);
EXPECT_EQ (v2s_2d (p), "0,-1");
}
TEST(5_CameraNormal)
{
QMatrix4x4 matrix;
QVector3D p;
matrix.perspective (60.0f, 1.5, 0.1f, 100.0f);
matrix.rotate (22.0, 1.0, 0.0, 0.0);
matrix.rotate (-15.0, 0.0, 1.0, 0.0);
matrix.translate (QVector3D (0.0, 0.0, 4.0));
std::pair<QVector3D, QVector3D> ray;
ray = lay::camera_normal (matrix, 0.0, 1.0);
EXPECT_EQ (v2s (ray.second), "-0.2563,0.139173,-0.956526");
p = matrix.map (ray.first);
EXPECT_EQ (v2s_2d (p), "0,1");
p = matrix.map (ray.first + ray.second);
EXPECT_EQ (v2s_2d (p), "0,1");
p = matrix.map (ray.first + ray.second * 1000.0);
EXPECT_EQ (v2s_2d (p), "0,1");
}

View File

@ -7,6 +7,7 @@ include($$PWD/../../../../lib_ut.pri)
SOURCES = \
layD25MemChunksTests.cc \
layD25ViewUtilsTests.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