//============================================================================ // 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 #include #include namespace vtkm { namespace rendering { static void printMtx(const std::string &nm, const vtkm::Matrix &mtx) { std::cout< &v) { std::cout< CreateViewMatrix() { vtkm::Matrix V = View::ViewMtx(pos, lookAt, up); return V; } VTKM_CONT_EXPORT vtkm::Matrix CreateProjectionMatrix(vtkm::Int32 &width, vtkm::Int32 &height, vtkm::Float32 &nearPlane, vtkm::Float32 &farPlane) { vtkm::Matrix mtx; vtkm::MatrixIdentity(mtx); vtkm::Float32 AspectRatio = vtkm::Float32(width) / vtkm::Float32(height); vtkm::Float32 fovRad = (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; mtx(0,0) = 2.f * nearPlane / (right - left); mtx(1,1) = 2.f * nearPlane / (top - bottom); mtx(0,2) = (right + left) / (right - left); mtx(1,2) = (top + bottom) / (top - bottom); mtx(2,2) = -(farPlane + nearPlane) / (farPlane - nearPlane); mtx(3,2) = -1.f; mtx(2,3) = -(2.f * farPlane * nearPlane) / (farPlane - nearPlane); mtx(3,3) = 0.f; vtkm::Matrix T, Z; T = View::TranslateMtx(xpan, ypan, 0); Z = View::ScaleMtx(zoom, zoom, 1); mtx = vtkm::MatrixMultiply(Z, vtkm::MatrixMultiply(T, mtx)); return mtx; } vtkm::Vec up, lookAt, pos; vtkm::Float32 fieldOfView; vtkm::Float32 xpan, ypan, 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 CreateViewMatrix() { vtkm::Vec at((left+right)/2.f, (top+bottom)/2.f, 0.f); vtkm::Vec pos = at; pos[2] = 1.f; vtkm::Vec up(0,1,0); return View::ViewMtx(pos, at, up); } VTKM_CONT_EXPORT vtkm::Matrix CreateProjectionMatrix(vtkm::Float32 &size, vtkm::Float32 &near, vtkm::Float32 &far, vtkm::Float32 &aspect) { vtkm::Matrix mtx(0.f); vtkm::Float32 L = -size/2.f * aspect; vtkm::Float32 R = size/2.f * aspect; vtkm::Float32 B = -size/2.f; vtkm::Float32 T = size/2.f; mtx(0,0) = 2.f/(R-L); mtx(1,1) = 2.f/(T-B); mtx(2,2) = -2.f/(far-near); mtx(0,3) = -(R+L)/(R-L); mtx(1,3) = -(T+B)/(T-B); mtx(2,3) = -(far+near)/(far-near); mtx(3,3) = 1.f; return mtx; } vtkm::Float32 left, right, top, bottom; vtkm::Float32 xScale; }; private: static VTKM_CONT_EXPORT vtkm::Matrix ViewMtx(const vtkm::Vec &pos, const vtkm::Vec &at, const vtkm::Vec &up) { vtkm::Vec viewDir = pos-at; vtkm::Vec right = vtkm::Cross(up,viewDir); vtkm::Vec ru = vtkm::Cross(viewDir,right); vtkm::Normalize(viewDir); vtkm::Normalize(right); vtkm::Normalize(ru); vtkm::Matrix mtx; vtkm::MatrixIdentity(mtx); mtx(0,0) = right[0]; mtx(0,1) = right[1]; mtx(0,2) = right[2]; mtx(1,0) = ru[0]; mtx(1,1) = ru[1]; mtx(1,2) = ru[2]; mtx(2,0) = viewDir[0]; mtx(2,1) = viewDir[1]; mtx(2,2) = viewDir[2]; mtx(0,3) = -vtkm::dot(right,pos); mtx(1,3) = -vtkm::dot(ru,pos); mtx(2,3) = -vtkm::dot(viewDir,pos); return mtx; } static VTKM_CONT_EXPORT vtkm::Matrix ScaleMtx(const vtkm::Vec &v) { return ScaleMtx(v[0], v[1], v[2]); } static VTKM_CONT_EXPORT vtkm::Matrix ScaleMtx(const vtkm::Float32 &s) {return ScaleMtx(s,s,s);} static VTKM_CONT_EXPORT vtkm::Matrix ScaleMtx(const vtkm::Float32 &x, const vtkm::Float32 &y, const vtkm::Float32 &z) { vtkm::Matrix S; vtkm::MatrixIdentity(S); S(0,0) = x; S(1,1) = y; S(2,2) = z; return S; } static VTKM_CONT_EXPORT vtkm::Matrix TranslateMtx(const vtkm::Vec &v) { return TranslateMtx(v[0], v[1], v[2]); } static VTKM_CONT_EXPORT vtkm::Matrix TranslateMtx(const vtkm::Float32 &x, const vtkm::Float32 &y, const vtkm::Float32 &z) { vtkm::Matrix T; vtkm::MatrixIdentity(T); T(0,3) = x; T(1,3) = y; T(2,3) = z; return T; } VTKM_CONT_EXPORT vtkm::Matrix CreateTrackball(vtkm::Float32 p1x, vtkm::Float32 p1y, vtkm::Float32 p2x, vtkm::Float32 p2y) { const vtkm::Float32 RADIUS = 0.80f; //z value at x = y = 0.0 const vtkm::Float32 COMPRESSION = 3.5f; // multipliers for x and y. const vtkm::Float32 AR3 = RADIUS*RADIUS*RADIUS; vtkm::Matrix mtx; vtkm::MatrixIdentity(mtx); if (p1x==p2x && p1y==p2y) return mtx; vtkm::Vec p1(p1x,p1y, AR3/((p1x*p1x+p1y*p1y)*COMPRESSION+AR3)); vtkm::Vec p2(p2x,p2y, AR3/((p2x*p2x+p2y*p2y)*COMPRESSION+AR3)); vtkm::Vec axis = vtkm::Normal(vtkm::Cross(p2,p1)); //std::cout<<"Axis: "< 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(-2.0f*asin(t/(2.0f*RADIUS))); vtkm::Float32 val = static_cast(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(cos(phi/2.0f))}; // normalize quaternion to unit magnitude t = 1.0f / static_cast(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: "< CreateViewMatrix() { if (viewType == View::VIEW_3D) return view3d.CreateViewMatrix(); else return view2d.CreateViewMatrix(); } VTKM_CONT_EXPORT vtkm::Matrix CreateProjectionMatrix() { if (viewType == View::VIEW_3D) return view3d.CreateProjectionMatrix(width, height, nearPlane, farPlane); else { vtkm::Float32 size = vtkm::Abs(view2d.top-view2d.bottom); vtkm::Float32 l,r,b,t; GetRealViewport(l,r,b,t); vtkm::Float32 aspect = (static_cast(width)*(r-l)) / (static_cast(height)*(t-b)); return view2d.CreateProjectionMatrix(size, nearPlane, farPlane, aspect); } } VTKM_CONT_EXPORT void GetRealViewport(vtkm::Float32 &l, vtkm::Float32 &r, vtkm::Float32 &b, vtkm::Float32 &t) { if (viewType == View::VIEW_3D) { l = vl; r = vr; b = vb; t = vt; } else { vtkm::Float32 maxvw = (vr-vl) * static_cast(width); vtkm::Float32 maxvh = (vt-vb) * static_cast(height); vtkm::Float32 waspect = maxvw / maxvh; vtkm::Float32 daspect = (view2d.right - view2d.left) / (view2d.top - view2d.bottom); daspect *= view2d.xScale; //cerr << "waspect="< "< "< R1 = CreateTrackball(x1,y1, x2,y2); //Translate mtx vtkm::Matrix T1 = View::TranslateMtx(-view3d.lookAt); //vtkm::MatrixIdentity(T1); //T1(0,3) = -view3d.lookAt[0]; //T1(1,3) = -view3d.lookAt[1]; //T1(2,3) = -view3d.lookAt[2]; //Translate mtx vtkm::Matrix T2 = View::TranslateMtx(view3d.lookAt); //T2(0,3) = view3d.lookAt[0]; //T2(1,3) = view3d.lookAt[1]; //T2(2,3) = view3d.lookAt[2]; vtkm::Matrix V1 = CreateViewMatrix(); V1(0,3) = 0; V1(1,3) = 0; V1(2,3) = 0; vtkm::Matrix V2 = vtkm::MatrixTranspose(V1); //MM = T2 * V2 * R1 * V1 * T1; vtkm::Matrix MM; MM = vtkm::MatrixMultiply(T2, vtkm::MatrixMultiply(V2, vtkm::MatrixMultiply(R1, vtkm::MatrixMultiply(V1,T1)))); view3d.pos = MultVector(MM, view3d.pos); view3d.lookAt = MultVector(MM, view3d.lookAt); view3d.up = MultVector(MM, view3d.up); /* printMtx("T1", T1); printMtx("T2", T2); printMtx("V1", V1); printMtx("V2", V2); printMtx("R1", R1); printMtx("MM", MM); printVec("pos", view3d.pos); printVec("at", view3d.lookAt); printVec("up", view3d.up); */ } }; }} // namespace vtkm::rendering #endif // vtk_m_rendering_View_h