vtk-m2/vtkm/rendering/View.h
Kenneth Moreland 732a45ff3b Fix shadowed variable warnings and style for View.h
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.
2016-05-19 16:37:37 -06:00

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