732a45ff3b
Several of the methods in View.h were giving me warnings about shadowed variables because the name of the arguments were the same as some class member variables. I fixed this by changing the variable names to match the VTK-m coding convention of using capitalized words for class member variables and starting lower case letter for method arguments and local variables. Since this ended up changing over half of the lines of View.h and Camera.h anyway, I also made some other modifications to the style to put it in alignment with VTK-m coding conventions including 2-space indentation and more descriptive variable names.
484 lines
15 KiB
C++
484 lines
15 KiB
C++
//============================================================================
|
|
// Copyright (c) Kitware, Inc.
|
|
// All rights reserved.
|
|
// See LICENSE.txt for details.
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
//
|
|
// Copyright 2015 Sandia Corporation.
|
|
// Copyright 2015 UT-Battelle, LLC.
|
|
// Copyright 2015 Los Alamos National Security.
|
|
//
|
|
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
|
// the U.S. Government retains certain rights in this software.
|
|
//
|
|
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
|
// Laboratory (LANL), the U.S. Government retains certain rights in
|
|
// this software.
|
|
//============================================================================
|
|
#ifndef vtk_m_rendering_View_h
|
|
#define vtk_m_rendering_View_h
|
|
#include <vtkm/Math.h>
|
|
#include <vtkm/Matrix.h>
|
|
#include <vtkm/VectorAnalysis.h>
|
|
|
|
namespace vtkm {
|
|
namespace rendering {
|
|
|
|
class View
|
|
{
|
|
class View3D
|
|
{
|
|
public:
|
|
VTKM_CONT_EXPORT
|
|
View3D() : FieldOfView(0.f), XPan(0), YPan(0), Zoom(1)
|
|
{}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> CreateViewMatrix()
|
|
{
|
|
return View::ViewMatrix(this->Position, this->LookAt, this->Up);
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> CreateProjectionMatrix(vtkm::Int32 &width,
|
|
vtkm::Int32 &height,
|
|
vtkm::Float32 &nearPlane,
|
|
vtkm::Float32 &farPlane)
|
|
{
|
|
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
|
vtkm::MatrixIdentity(matrix);
|
|
|
|
vtkm::Float32 AspectRatio = vtkm::Float32(width) / vtkm::Float32(height);
|
|
vtkm::Float32 fovRad = (this->FieldOfView * 3.1415926f)/180.f;
|
|
fovRad = vtkm::Tan( fovRad * 0.5f);
|
|
vtkm::Float32 size = nearPlane * fovRad;
|
|
vtkm::Float32 left = -size * AspectRatio;
|
|
vtkm::Float32 right = size * AspectRatio;
|
|
vtkm::Float32 bottom = -size;
|
|
vtkm::Float32 top = size;
|
|
|
|
matrix(0,0) = 2.f * nearPlane / (right - left);
|
|
matrix(1,1) = 2.f * nearPlane / (top - bottom);
|
|
matrix(0,2) = (right + left) / (right - left);
|
|
matrix(1,2) = (top + bottom) / (top - bottom);
|
|
matrix(2,2) = -(farPlane + nearPlane) / (farPlane - nearPlane);
|
|
matrix(3,2) = -1.f;
|
|
matrix(2,3) = -(2.f * farPlane * nearPlane) / (farPlane - nearPlane);
|
|
matrix(3,3) = 0.f;
|
|
|
|
vtkm::Matrix<vtkm::Float32,4,4> T, Z;
|
|
T = View::TranslateMatrix(this->XPan, this->YPan, 0);
|
|
Z = View::ScaleMatrix(this->Zoom, this->Zoom, 1);
|
|
matrix = vtkm::MatrixMultiply(Z, vtkm::MatrixMultiply(T, matrix));
|
|
return matrix;
|
|
}
|
|
|
|
|
|
vtkm::Vec<vtkm::Float32,3> Up;
|
|
vtkm::Vec<vtkm::Float32,3> LookAt;
|
|
vtkm::Vec<vtkm::Float32,3> Position;
|
|
vtkm::Float32 FieldOfView;
|
|
vtkm::Float32 XPan;
|
|
vtkm::Float32 YPan;
|
|
vtkm::Float32 Zoom;
|
|
};
|
|
|
|
class View2D
|
|
{
|
|
public:
|
|
VTKM_CONT_EXPORT
|
|
View2D() : Left(0.f), Right(0.f), Top(0.f), Bottom(0.f), XScale(1.f)
|
|
{}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> CreateViewMatrix()
|
|
{
|
|
vtkm::Vec<vtkm::Float32,3> lookAt((this->Left + this->Right)/2.f,
|
|
(this->Top + this->Bottom)/2.f,
|
|
0.f);
|
|
vtkm::Vec<vtkm::Float32,3> position = lookAt;
|
|
position[2] = 1.f;
|
|
vtkm::Vec<vtkm::Float32,3> up(0,1,0);
|
|
return View::ViewMatrix(position, lookAt, up);
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> CreateProjectionMatrix(vtkm::Float32 &size,
|
|
vtkm::Float32 &near,
|
|
vtkm::Float32 &far,
|
|
vtkm::Float32 &aspect)
|
|
{
|
|
vtkm::Matrix<vtkm::Float32,4,4> matrix(0.f);
|
|
vtkm::Float32 left = -size/2.f * aspect;
|
|
vtkm::Float32 right = size/2.f * aspect;
|
|
vtkm::Float32 bottom = -size/2.f;
|
|
vtkm::Float32 top = size/2.f;
|
|
|
|
matrix(0,0) = 2.f/(right-left);
|
|
matrix(1,1) = 2.f/(top-bottom);
|
|
matrix(2,2) = -2.f/(far-near);
|
|
matrix(0,3) = -(right+left)/(right-left);
|
|
matrix(1,3) = -(top+bottom)/(top-bottom);
|
|
matrix(2,3) = -(far+near)/(far-near);
|
|
matrix(3,3) = 1.f;
|
|
return matrix;
|
|
}
|
|
|
|
vtkm::Float32 Left;
|
|
vtkm::Float32 Right;
|
|
vtkm::Float32 Top;
|
|
vtkm::Float32 Bottom;
|
|
vtkm::Float32 XScale;
|
|
};
|
|
|
|
private:
|
|
static VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> ViewMatrix(const vtkm::Vec<vtkm::Float32,3> &position,
|
|
const vtkm::Vec<vtkm::Float32,3> &lookAt,
|
|
const vtkm::Vec<vtkm::Float32,3> &up)
|
|
{
|
|
vtkm::Vec<vtkm::Float32,3> viewDir = position-lookAt;
|
|
vtkm::Vec<vtkm::Float32,3> right = vtkm::Cross(up,viewDir);
|
|
vtkm::Vec<vtkm::Float32,3> ru = vtkm::Cross(viewDir,right);
|
|
|
|
vtkm::Normalize(viewDir);
|
|
vtkm::Normalize(right);
|
|
vtkm::Normalize(ru);
|
|
|
|
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
|
vtkm::MatrixIdentity(matrix);
|
|
|
|
matrix(0,0) = right[0];
|
|
matrix(0,1) = right[1];
|
|
matrix(0,2) = right[2];
|
|
matrix(1,0) = ru[0];
|
|
matrix(1,1) = ru[1];
|
|
matrix(1,2) = ru[2];
|
|
matrix(2,0) = viewDir[0];
|
|
matrix(2,1) = viewDir[1];
|
|
matrix(2,2) = viewDir[2];
|
|
|
|
matrix(0,3) = -vtkm::dot(right,position);
|
|
matrix(1,3) = -vtkm::dot(ru,position);
|
|
matrix(2,3) = -vtkm::dot(viewDir,position);
|
|
|
|
return matrix;
|
|
}
|
|
|
|
static VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Vec<vtkm::Float32,3> &v)
|
|
{
|
|
return ScaleMatrix(v[0], v[1], v[2]);
|
|
}
|
|
static VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Float32 &s)
|
|
{
|
|
return ScaleMatrix(s,s,s);
|
|
}
|
|
|
|
static VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> ScaleMatrix(const vtkm::Float32 &x,
|
|
const vtkm::Float32 &y,
|
|
const vtkm::Float32 &z)
|
|
{
|
|
vtkm::Matrix<vtkm::Float32,4,4> scaleMatrix(0.0f);
|
|
scaleMatrix(0,0) = x;
|
|
scaleMatrix(1,1) = y;
|
|
scaleMatrix(2,2) = z;
|
|
scaleMatrix(3,3) = 1.0f;
|
|
return scaleMatrix;
|
|
}
|
|
|
|
static VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> TranslateMatrix(const vtkm::Vec<vtkm::Float32,3> &v)
|
|
{
|
|
return TranslateMatrix(v[0], v[1], v[2]);
|
|
}
|
|
|
|
static VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> TranslateMatrix(const vtkm::Float32 &x,
|
|
const vtkm::Float32 &y,
|
|
const vtkm::Float32 &z)
|
|
{
|
|
vtkm::Matrix<vtkm::Float32,4,4> translateMatrix;
|
|
vtkm::MatrixIdentity(translateMatrix);
|
|
translateMatrix(0,3) = x;
|
|
translateMatrix(1,3) = y;
|
|
translateMatrix(2,3) = z;
|
|
return translateMatrix;
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4>
|
|
CreateTrackball(vtkm::Float32 p1x, vtkm::Float32 p1y, vtkm::Float32 p2x, vtkm::Float32 p2y)
|
|
{
|
|
const vtkm::Float32 RADIUS = 0.80f; //z value lookAt x = y = 0.0
|
|
const vtkm::Float32 COMPRESSION = 3.5f; // multipliers for x and y.
|
|
const vtkm::Float32 AR3 = RADIUS*RADIUS*RADIUS;
|
|
|
|
vtkm::Matrix<vtkm::Float32,4,4> matrix;
|
|
|
|
vtkm::MatrixIdentity(matrix);
|
|
if (p1x==p2x && p1y==p2y) { return matrix; }
|
|
|
|
vtkm::Vec<vtkm::Float32, 3> p1(p1x,p1y, AR3/((p1x*p1x+p1y*p1y)*COMPRESSION+AR3));
|
|
vtkm::Vec<vtkm::Float32, 3> p2(p2x,p2y, AR3/((p2x*p2x+p2y*p2y)*COMPRESSION+AR3));
|
|
vtkm::Vec<vtkm::Float32, 3> axis = vtkm::Normal(vtkm::Cross(p2,p1));
|
|
//std::cout<<"Axis: "<<axis[0]<<" "<<axis[1]<<" "<<axis[2]<<std::endl;
|
|
|
|
vtkm::Vec<vtkm::Float32, 3> p2_p1(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]);
|
|
vtkm::Float32 t = vtkm::Magnitude(p2_p1);
|
|
t = vtkm::Min(vtkm::Max(t, -1.0f), 1.0f);
|
|
vtkm::Float32 phi = static_cast<vtkm::Float32>(-2.0f*asin(t/(2.0f*RADIUS)));
|
|
vtkm::Float32 val = static_cast<vtkm::Float32>(sin(phi/2.0f));
|
|
axis[0] *= val;
|
|
axis[1] *= val;
|
|
axis[2] *= val;
|
|
|
|
//quaternion
|
|
vtkm::Float32 q[4] = {axis[0], axis[1], axis[2], static_cast<vtkm::Float32>(cos(phi/2.0f))};
|
|
|
|
// normalize quaternion to unit magnitude
|
|
t = 1.0f / static_cast<vtkm::Float32>(sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]));
|
|
q[0] *= t;
|
|
q[1] *= t;
|
|
q[2] *= t;
|
|
q[3] *= t;
|
|
|
|
/*
|
|
std::cout<<"P1: "<<p1[0]<<" "<<p1[1]<<" "<<p1[2]<<std::endl;
|
|
std::cout<<"P2: "<<p2[0]<<" "<<p2[1]<<" "<<p2[2]<<std::endl;
|
|
std::cout<<"T= "<<t<<std::endl;
|
|
std::cout<<"PHI= "<<phi<<std::endl;
|
|
std::cout<<"QUAT: "<<q[0]<<" "<<q[1]<<" "<<q[2]<<" "<<q[3]<<std::endl;
|
|
*/
|
|
|
|
matrix(0,0) = 1 - 2 * (q[1]*q[1] + q[2]*q[2]);
|
|
matrix(0,1) = 2 * (q[0]*q[1] + q[2]*q[3]);
|
|
matrix(0,2) = (2 * (q[2]*q[0] - q[1]*q[3]) );
|
|
|
|
matrix(1,0) = 2 * (q[0]*q[1] - q[2]*q[3]);
|
|
matrix(1,1) = 1 - 2 * (q[2]*q[2] + q[0]*q[0]);
|
|
matrix(1,2) = (2 * (q[1]*q[2] + q[0]*q[3]) );
|
|
|
|
matrix(2,0) = (2 * (q[2]*q[0] + q[1]*q[3]) );
|
|
matrix(2,1) = (2 * (q[1]*q[2] - q[0]*q[3]) );
|
|
matrix(2,2) = (1 - 2 * (q[1]*q[1] + q[0]*q[0]) );
|
|
|
|
return matrix;
|
|
}
|
|
|
|
|
|
public:
|
|
enum ViewTypeEnum { VIEW_2D, VIEW_3D };
|
|
ViewTypeEnum ViewType;
|
|
View3D View3d;
|
|
View2D View2d;
|
|
|
|
vtkm::Int32 Width;
|
|
vtkm::Int32 Height;
|
|
vtkm::Float32 NearPlane;
|
|
vtkm::Float32 FarPlane;
|
|
|
|
vtkm::Float32 ViewportLeft;
|
|
vtkm::Float32 ViewportRight;
|
|
vtkm::Float32 ViewportBottom;
|
|
vtkm::Float32 ViewportTop;
|
|
|
|
VTKM_CONT_EXPORT
|
|
View(ViewTypeEnum vtype=View::VIEW_3D)
|
|
: ViewType(vtype),
|
|
Width(-1),
|
|
Height(-1),
|
|
NearPlane(0.f),
|
|
FarPlane(1.f),
|
|
ViewportLeft(-1.f),
|
|
ViewportRight(1.f),
|
|
ViewportBottom(-1.f),
|
|
ViewportTop(1.f)
|
|
{}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> CreateViewMatrix()
|
|
{
|
|
if (this->ViewType == View::VIEW_3D)
|
|
{
|
|
return this->View3d.CreateViewMatrix();
|
|
}
|
|
else
|
|
{
|
|
return this->View2d.CreateViewMatrix();
|
|
}
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Matrix<vtkm::Float32,4,4> CreateProjectionMatrix()
|
|
{
|
|
if (this->ViewType == View::VIEW_3D)
|
|
{
|
|
return this->View3d.CreateProjectionMatrix(
|
|
this->Width, this->Height, this->NearPlane, this->FarPlane);
|
|
}
|
|
else
|
|
{
|
|
vtkm::Float32 size = vtkm::Abs(this->View2d.Top - this->View2d.Bottom);
|
|
vtkm::Float32 left,right,bottom,top;
|
|
this->GetRealViewport(left,right,bottom,top);
|
|
vtkm::Float32 aspect =
|
|
(static_cast<vtkm::Float32>(this->Width)*(right-left)) /
|
|
(static_cast<vtkm::Float32>(this->Height)*(top-bottom));
|
|
|
|
return this->View2d.CreateProjectionMatrix(
|
|
size, this->NearPlane, this->FarPlane, aspect);
|
|
}
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
void GetRealViewport(vtkm::Float32 &left, vtkm::Float32 &right,
|
|
vtkm::Float32 &bottom, vtkm::Float32 &top)
|
|
{
|
|
if (this->ViewType == View::VIEW_3D)
|
|
{
|
|
left = this->ViewportLeft;
|
|
right = this->ViewportRight;
|
|
bottom = this->ViewportBottom;
|
|
top = this->ViewportTop;
|
|
}
|
|
else
|
|
{
|
|
vtkm::Float32 maxvw = (this->ViewportRight-this->ViewportLeft) * static_cast<vtkm::Float32>(this->Width);
|
|
vtkm::Float32 maxvh = (this->ViewportTop-this->ViewportBottom) * static_cast<vtkm::Float32>(this->Height);
|
|
vtkm::Float32 waspect = maxvw / maxvh;
|
|
vtkm::Float32 daspect = (this->View2d.Right - this->View2d.Left) / (this->View2d.Top - this->View2d.Bottom);
|
|
daspect *= this->View2d.XScale;
|
|
//cerr << "waspect="<<waspect << " \tdaspect="<<daspect<<endl;
|
|
const bool center = true; // if false, anchor to bottom-left
|
|
if (waspect > daspect)
|
|
{
|
|
vtkm::Float32 new_w = (this->ViewportRight-this->ViewportLeft) * daspect / waspect;
|
|
if (center)
|
|
{
|
|
left = (this->ViewportLeft+this->ViewportRight)/2.f - new_w/2.f;
|
|
right = (this->ViewportLeft+this->ViewportRight)/2.f + new_w/2.f;
|
|
}
|
|
else
|
|
{
|
|
left = this->ViewportLeft;
|
|
right = this->ViewportLeft + new_w;
|
|
}
|
|
bottom = this->ViewportBottom;
|
|
top = this->ViewportTop;
|
|
}
|
|
else
|
|
{
|
|
vtkm::Float32 new_h = (this->ViewportTop-this->ViewportBottom) * waspect / daspect;
|
|
if (center)
|
|
{
|
|
bottom = (this->ViewportBottom+this->ViewportTop)/2.f - new_h/2.f;
|
|
top = (this->ViewportBottom+this->ViewportTop)/2.f + new_h/2.f;
|
|
}
|
|
else
|
|
{
|
|
bottom = this->ViewportBottom;
|
|
top = this->ViewportBottom + new_h;
|
|
}
|
|
left = this->ViewportLeft;
|
|
right = this->ViewportRight;
|
|
}
|
|
}
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
vtkm::Vec<vtkm::Float32, 3>
|
|
MultVector(const vtkm::Matrix<vtkm::Float32,4,4> &matrix, vtkm::Vec<vtkm::Float32, 3> &v)
|
|
{
|
|
vtkm::Vec<vtkm::Float32,4> v4(v[0],v[1],v[2], 1);
|
|
v4 = vtkm::MatrixMultiply(matrix, v4);
|
|
v[0] = v4[0];
|
|
v[1] = v4[1];
|
|
v[2] = v4[2];
|
|
return v;
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
void Pan3D(vtkm::Float32 dx, vtkm::Float32 dy)
|
|
{
|
|
//std::cout<<"Pan3d: "<<dx<<" "<<dy<<std::endl;
|
|
this->View3d.XPan += dx;
|
|
this->View3d.YPan += dy;
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
void Zoom3D(vtkm::Float32 zoom)
|
|
{
|
|
vtkm::Float32 factor = powf(4, zoom);
|
|
//std::cout<<"Zoom3D: "<<zoom<<" --> "<<factor<<std::endl;
|
|
this->View3d.Zoom *= factor;
|
|
this->View3d.XPan *= factor;
|
|
this->View3d.YPan *= factor;
|
|
}
|
|
|
|
VTKM_CONT_EXPORT
|
|
void TrackballRotate(vtkm::Float32 x1, vtkm::Float32 y1, vtkm::Float32 x2, vtkm::Float32 y2)
|
|
{
|
|
/*
|
|
std::cout<<std::endl;
|
|
std::cout<<"*****************************************************************"<<std::endl;
|
|
std::cout<<x1<<" "<<y1<<" --> "<<x2<<" "<<y2<<std::endl;
|
|
printVec("position", view3d.Position);
|
|
printVec("lookAt", view3d.lookAt);
|
|
printVec("up", view3d.up);
|
|
std::cout<<"*****************************************************************"<<std::endl;
|
|
*/
|
|
vtkm::Matrix<vtkm::Float32,4,4> R1 = CreateTrackball(x1,y1, x2,y2);
|
|
|
|
//Translate matrix
|
|
vtkm::Matrix<vtkm::Float32,4,4> T1 = View::TranslateMatrix(-this->View3d.LookAt);
|
|
//vtkm::MatrixIdentity(T1);
|
|
//T1(0,3) = -view3d.lookAt[0];
|
|
//T1(1,3) = -view3d.lookAt[1];
|
|
//T1(2,3) = -view3d.lookAt[2];
|
|
|
|
//Translate matrix
|
|
vtkm::Matrix<vtkm::Float32,4,4> T2 = View::TranslateMatrix(this->View3d.LookAt);
|
|
//T2(0,3) = view3d.lookAt[0];
|
|
//T2(1,3) = view3d.lookAt[1];
|
|
//T2(2,3) = view3d.lookAt[2];
|
|
|
|
vtkm::Matrix<vtkm::Float32,4,4> V1 = this->CreateViewMatrix();
|
|
V1(0,3) = 0;
|
|
V1(1,3) = 0;
|
|
V1(2,3) = 0;
|
|
|
|
vtkm::Matrix<vtkm::Float32,4,4> V2 = vtkm::MatrixTranspose(V1);
|
|
|
|
//MM = T2 * V2 * R1 * V1 * T1;
|
|
vtkm::Matrix<vtkm::Float32,4,4> MM;
|
|
MM = vtkm::MatrixMultiply(T2,
|
|
vtkm::MatrixMultiply(V2,
|
|
vtkm::MatrixMultiply(R1,
|
|
vtkm::MatrixMultiply(V1,T1))));
|
|
this->View3d.Position = MultVector(MM, this->View3d.Position);
|
|
this->View3d.LookAt = MultVector(MM, this->View3d.LookAt);
|
|
this->View3d.Up = MultVector(MM, this->View3d.Up);
|
|
|
|
/*
|
|
printMtx("T1", T1);
|
|
printMtx("T2", T2);
|
|
printMtx("V1", V1);
|
|
printMtx("V2", V2);
|
|
printMtx("R1", R1);
|
|
printMtx("MM", MM);
|
|
printVec("position", this->View3d.Position);
|
|
printVec("lookAt", this->View3d.LookAt);
|
|
printVec("up", this->View3d.Up);
|
|
*/
|
|
}
|
|
};
|
|
|
|
}} // namespace vtkm::rendering
|
|
|
|
#endif // vtk_m_rendering_View_h
|