Edit 3
I'm happy to announce that some of the code of this answer is now included in the Tikz package (v3.1.2) as the perspective
library.
Edit 2
Using this awesome answer in combination with my tpp
coordinate system, I managed to get an approximation of a nonlinear mapping to the side of the block.
Or without help lines:
Stationary image:
MWE:
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usepgfmodule{nonlineartransformations}
\usepackage{mathtools}
\makeatletter
\def\tikz@scan@transform@one@point#1{%
\tikz@scan@one@point\pgf@process#1%
\pgf@pos@transform{\pgf@x}{\pgf@y}}
\tikzset{%
grid source opposite corners/.code args={#1and#2}{%
\pgfextract@process\tikz@transform@source@southwest{%
\tikz@scan@transform@one@point{#1}}%
\pgfextract@process\tikz@transform@source@northeast{%
\tikz@scan@transform@one@point{#2}}%
},
grid target corners/.code args={#1--#2--#3--#4}{%
\pgfextract@process\tikz@transform@target@southwest{%
\tikz@scan@transform@one@point{#1}}%
\pgfextract@process\tikz@transform@target@southeast{%
\tikz@scan@transform@one@point{#2}}%
\pgfextract@process\tikz@transform@target@northeast{%
\tikz@scan@transform@one@point{#3}}%
\pgfextract@process\tikz@transform@target@northwest{%
\tikz@scan@transform@one@point{#4}}%
}
}
\def\tikzgridtransform{%
\pgfextract@process\tikz@current@point{}%
\pgf@process{%
\pgfpointdiff{\tikz@transform@source@southwest}%
{\tikz@transform@source@northeast}%
}%
\pgf@xc=\pgf@x\pgf@yc=\pgf@y%
\pgf@process{%
\pgfpointdiff{\tikz@transform@source@southwest}{\tikz@current@point}%
}%
\pgfmathparse{\pgf@x/\pgf@xc}\let\tikz@tx=\pgfmathresult%
\pgfmathparse{\pgf@y/\pgf@yc}\let\tikz@ty=\pgfmathresult%
%
\pgfpointlineattime{\tikz@ty}{%
\pgfpointlineattime{\tikz@tx}{\tikz@transform@target@southwest}%
{\tikz@transform@target@southeast}}{%
\pgfpointlineattime{\tikz@tx}{\tikz@transform@target@northwest}%
{\tikz@transform@target@northeast}}%
}
% Initialize H matrix for perspective view
\pgfmathsetmacro\H@tpp@aa{1}\pgfmathsetmacro\H@tpp@ab{0}\pgfmathsetmacro\H@tpp@ac{0}%\pgfmathsetmacro\H@tpp@ad{0}
\pgfmathsetmacro\H@tpp@ba{0}\pgfmathsetmacro\H@tpp@bb{1}\pgfmathsetmacro\H@tpp@bc{0}%\pgfmathsetmacro\H@tpp@bd{0}
\pgfmathsetmacro\H@tpp@ca{0}\pgfmathsetmacro\H@tpp@cb{0}\pgfmathsetmacro\H@tpp@cc{1}%\pgfmathsetmacro\H@tpp@cd{0}
\pgfmathsetmacro\H@tpp@da{0}\pgfmathsetmacro\H@tpp@db{0}\pgfmathsetmacro\H@tpp@dc{0}%\pgfmathsetmacro\H@tpp@dd{1}
%Initialize H matrix for main rotation
\pgfmathsetmacro\H@rot@aa{1}\pgfmathsetmacro\H@rot@ab{0}\pgfmathsetmacro\H@rot@ac{0}%\pgfmathsetmacro\H@rot@ad{0}
\pgfmathsetmacro\H@rot@ba{0}\pgfmathsetmacro\H@rot@bb{1}\pgfmathsetmacro\H@rot@bc{0}%\pgfmathsetmacro\H@rot@bd{0}
\pgfmathsetmacro\H@rot@ca{0}\pgfmathsetmacro\H@rot@cb{0}\pgfmathsetmacro\H@rot@cc{1}%\pgfmathsetmacro\H@rot@cd{0}
%\pgfmathsetmacro\H@rot@da{0}\pgfmathsetmacro\H@rot@db{0}\pgfmathsetmacro\H@rot@dc{0}\pgfmathsetmacro\H@rot@dd{1}
\pgfkeys{
/three point perspective/.cd,
p/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#1))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ba{#2/#1}
\pgfmathsetmacro\H@tpp@ca{#3/#1}
\pgfmathsetmacro\H@tpp@da{ 1/#1}
\coordinate (vp-p) at (#1,#2,#3);
\fi
},
q/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#2))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ab{#1/#2}
\pgfmathsetmacro\H@tpp@cb{#3/#2}
\pgfmathsetmacro\H@tpp@db{ 1/#2}
\coordinate (vp-q) at (#1,#2,#3);
\fi
},
r/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#3))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ac{#1/#3}
\pgfmathsetmacro\H@tpp@bc{#2/#3}
\pgfmathsetmacro\H@tpp@dc{ 1/#3}
\coordinate (vp-r) at (#1,#2,#3);
\fi
},
coordinate/.code args={#1,#2,#3}{
\def\tpp@x{#1}
\def\tpp@y{#2}
\def\tpp@z{#3}
},
}
\tikzset{
view/.code 2 args={
\pgfmathsetmacro\rot@main@theta{#1}
\pgfmathsetmacro\rot@main@phi{#2}
% Row 1
\pgfmathsetmacro\H@rot@aa{cos(\rot@main@phi)}
\pgfmathsetmacro\H@rot@ab{sin(\rot@main@phi)}
\pgfmathsetmacro\H@rot@ac{0}
% Row 2
\pgfmathsetmacro\H@rot@ba{-cos(\rot@main@theta)*sin(\rot@main@phi)}
\pgfmathsetmacro\H@rot@bb{cos(\rot@main@phi)*cos(\rot@main@theta)}
\pgfmathsetmacro\H@rot@bc{sin(\rot@main@theta)}
% Row 3
\pgfmathsetmacro\H@m@ca{sin(\rot@main@phi)*sin(\rot@main@theta)}
\pgfmathsetmacro\H@m@cb{-cos(\rot@main@phi)*sin(\rot@main@theta)}
\pgfmathsetmacro\H@m@cc{cos(\rot@main@theta)}
% Set vector values
\pgfmathsetmacro\vec@x@x{\H@rot@aa}
\pgfmathsetmacro\vec@y@x{\H@rot@ab}
\pgfmathsetmacro\vec@z@x{\H@rot@ac}
\pgfmathsetmacro\vec@x@y{\H@rot@ba}
\pgfmathsetmacro\vec@y@y{\H@rot@bb}
\pgfmathsetmacro\vec@z@y{\H@rot@bc}
% Set pgf vectors
\pgfsetxvec{\pgfpoint{\vec@x@x cm}{\vec@x@y cm}}
\pgfsetyvec{\pgfpoint{\vec@y@x cm}{\vec@y@y cm}}
\pgfsetzvec{\pgfpoint{\vec@z@x cm}{\vec@z@y cm}}
},
}
\tikzset{
perspective/.code={\pgfkeys{/three point perspective/.cd,#1}},
perspective/.default={p={(15,0,0)},q={(0,15,0)},r={(0,0,50)}},
}
\tikzdeclarecoordinatesystem{three point perspective}{
\pgfkeys{/three point perspective/.cd,coordinate={#1}}
\pgfmathsetmacro\temp@p@w{\H@tpp@da*\tpp@x + \H@tpp@db*\tpp@y + \H@tpp@dc*\tpp@z + 1}
\pgfmathsetmacro\temp@p@x{(\H@tpp@aa*\tpp@x + \H@tpp@ab*\tpp@y + \H@tpp@ac*\tpp@z)/\temp@p@w}
\pgfmathsetmacro\temp@p@y{(\H@tpp@ba*\tpp@x + \H@tpp@bb*\tpp@y + \H@tpp@bc*\tpp@z)/\temp@p@w}
\pgfmathsetmacro\temp@p@z{(\H@tpp@ca*\tpp@x + \H@tpp@cb*\tpp@y + \H@tpp@cc*\tpp@z)/\temp@p@w}
\pgfpointxyz{\temp@p@x}{\temp@p@y}{\temp@p@z}
}
\tikzaliascoordinatesystem{tpp}{three point perspective}
\makeatother
\definecolor{mydarkbluishgray}{RGB}{134 134 191}
\definecolor{mylightbluishgray}{RGB}{215 215 255}
\begin{document}
\foreach \vp in {10,12.5,...,50}{
% \foreach \vp in {10}{
\begin{tikzpicture}[line join=round]
\clip (-12,0) rectangle (12,10);
\begin{scope}[
view={85}{-40},
perspective={
p = {(\vp,0,5.5)},
q = {(0,\vp,5.5)},
}
]
\fill[mydarkbluishgray] (tpp cs:0,0,0) -- (tpp cs:0,0,10) -- (tpp cs:0,5,10) -- (tpp cs:0,5,0) -- cycle;
\fill[mylightbluishgray] (tpp cs:0,0,0) -- (tpp cs:0,0,10) -- (tpp cs:15,0,10) -- (tpp cs:15,0,0) -- cycle;
\begin{scope}[
grid source opposite corners={(0cm,0cm) and (15cm,10cm)},
grid target corners={(tpp cs:0,0,0)--(tpp cs:15,0,0)--(tpp cs:15,0,10)--(tpp cs:0,0,10)}
]
\pgftransformnonlinear\tikzgridtransform
% \draw[dotted] (0cm,4.75cm) -- (15cm,4.75cm);
% \draw[red] (0cm,5.00cm) -- (15cm,5.00cm);
% \draw[dotted] (0cm,5.25cm) -- (15cm,5.25cm);
%
% \draw[dotted] (6.1cm,0cm) -- (6.1cm,10cm);
% \draw[red] (7.5cm,0cm) -- (7.5cm,10cm);
% \draw[dotted] (8.9cm,0cm) -- (8.9cm,10cm);
\foreach \char [count=\i from -2] in {O,M,E,A,G}{
\pgftransformshift{\pgfpointadd{\pgfpoint{7.5cm}{5cm}}{\pgfpoint{\i *0.6cm}{0cm}}}
\pgftransformscale{2}
\pgfnode{rectangle}{center}{\char}{}{}
}
\end{scope}
% \begin{scope}[dotted,line width=0.2pt]
% \node[label=right:p,fill,circle,inner sep = 2pt] (p) at (vp-p){};
%
% \draw (tpp cs:0,0,10) -- (p.center);
% \draw (tpp cs:0,0,0) -- (p.center);
% \draw (tpp cs:0,5,10) -- (p.center);
% \draw (tpp cs:0,5,0) -- (p.center);
%
% \node[label=left:q,fill,circle,inner sep = 2pt] (q) at (vp-q){};
%
% \draw (tpp cs:0,0,10) -- (q.center);
% \draw (tpp cs:0,0,0) -- (q.center);
% \draw (tpp cs:15,0,10) -- (q.center);
% \draw (tpp cs:15,0,0) -- (q.center);
% \end{scope}
\end{scope}
\end{tikzpicture}
}
\end{document}
Edit See previous edits for my former answer
I defined a new coordinate system three point perspective
. It can be used as
\draw (three point perspective cs:0,0,0) -- (three point perspective cs:5,5,5);
Or slightly more convenient
\draw (tpp cs:0,0,0) -- (tpp cs:5,5,5);
To turn perspective view on, you can call the perspective={<options>}
Tikz-key. The options are:
p={(p_x,p_y,p_z)}
to set the vanishing point in x
direction, to turn of set p_x
to 0.
q={(q_x,q_y,q_z)}
to set the vanishing point in y
direction, to turn of set q_y
to 0.
r={(r_x,r_y,r_z)}
to set the vanishing point in z
direction, to turn of set r_z
to 0.
The default perspective is set to p={(15,0,0)},q={(0,15,0)},r={(0,0,50)}
.
To change the viewing angle, I also added a view={<rotate about x>}{<rotate about z>}
key. The latter ensures that I don't need the tikz-3dplot
any longer.
The result is similar, but is easier to use.
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usepackage{mathtools}
\makeatletter
% Initialize H matrix for perspective view
\pgfmathsetmacro\H@tpp@aa{1}\pgfmathsetmacro\H@tpp@ab{0}\pgfmathsetmacro\H@tpp@ac{0}%\pgfmathsetmacro\H@tpp@ad{0}
\pgfmathsetmacro\H@tpp@ba{0}\pgfmathsetmacro\H@tpp@bb{1}\pgfmathsetmacro\H@tpp@bc{0}%\pgfmathsetmacro\H@tpp@bd{0}
\pgfmathsetmacro\H@tpp@ca{0}\pgfmathsetmacro\H@tpp@cb{0}\pgfmathsetmacro\H@tpp@cc{1}%\pgfmathsetmacro\H@tpp@cd{0}
\pgfmathsetmacro\H@tpp@da{0}\pgfmathsetmacro\H@tpp@db{0}\pgfmathsetmacro\H@tpp@dc{0}%\pgfmathsetmacro\H@tpp@dd{1}
%Initialize H matrix for main rotation
\pgfmathsetmacro\H@rot@aa{1}\pgfmathsetmacro\H@rot@ab{0}\pgfmathsetmacro\H@rot@ac{0}%\pgfmathsetmacro\H@rot@ad{0}
\pgfmathsetmacro\H@rot@ba{0}\pgfmathsetmacro\H@rot@bb{1}\pgfmathsetmacro\H@rot@bc{0}%\pgfmathsetmacro\H@rot@bd{0}
\pgfmathsetmacro\H@rot@ca{0}\pgfmathsetmacro\H@rot@cb{0}\pgfmathsetmacro\H@rot@cc{1}%\pgfmathsetmacro\H@rot@cd{0}
%\pgfmathsetmacro\H@rot@da{0}\pgfmathsetmacro\H@rot@db{0}\pgfmathsetmacro\H@rot@dc{0}\pgfmathsetmacro\H@rot@dd{1}
\pgfkeys{
/three point perspective/.cd,
p/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#1))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ba{#2/#1}
\pgfmathsetmacro\H@tpp@ca{#3/#1}
\pgfmathsetmacro\H@tpp@da{ 1/#1}
\coordinate (vp-p) at (#1,#2,#3);
\fi
},
q/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#2))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ab{#1/#2}
\pgfmathsetmacro\H@tpp@cb{#3/#2}
\pgfmathsetmacro\H@tpp@db{ 1/#2}
\coordinate (vp-q) at (#1,#2,#3);
\fi
},
r/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#3))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ac{#1/#3}
\pgfmathsetmacro\H@tpp@bc{#2/#3}
\pgfmathsetmacro\H@tpp@dc{ 1/#3}
\coordinate (vp-r) at (#1,#2,#3);
\fi
},
coordinate/.code args={#1,#2,#3}{
\def\tpp@x{#1}
\def\tpp@y{#2}
\def\tpp@z{#3}
},
}
\tikzset{
view/.code 2 args={
\pgfmathsetmacro\rot@main@theta{#1}
\pgfmathsetmacro\rot@main@phi{#2}
% Row 1
\pgfmathsetmacro\H@rot@aa{cos(\rot@main@phi)}
\pgfmathsetmacro\H@rot@ab{sin(\rot@main@phi)}
\pgfmathsetmacro\H@rot@ac{0}
% Row 2
\pgfmathsetmacro\H@rot@ba{-cos(\rot@main@theta)*sin(\rot@main@phi)}
\pgfmathsetmacro\H@rot@bb{cos(\rot@main@phi)*cos(\rot@main@theta)}
\pgfmathsetmacro\H@rot@bc{sin(\rot@main@theta)}
% Row 3
\pgfmathsetmacro\H@m@ca{sin(\rot@main@phi)*sin(\rot@main@theta)}
\pgfmathsetmacro\H@m@cb{-cos(\rot@main@phi)*sin(\rot@main@theta)}
\pgfmathsetmacro\H@m@cc{cos(\rot@main@theta)}
\pgfmathsetmacro\vec@x@x{\H@rot@aa}
\pgfmathsetmacro\vec@y@x{\H@rot@ab}
\pgfmathsetmacro\vec@z@x{\H@rot@ac}
\pgfmathsetmacro\vec@x@y{\H@rot@ba}
\pgfmathsetmacro\vec@y@y{\H@rot@bb}
\pgfmathsetmacro\vec@z@y{\H@rot@bc}
\pgfsetxvec{\pgfpoint{\vec@x@x cm}{\vec@x@y cm}}
\pgfsetyvec{\pgfpoint{\vec@y@x cm}{\vec@y@y cm}}
\pgfsetzvec{\pgfpoint{\vec@z@x cm}{\vec@z@y cm}}
},
}
\tikzset{
perspective/.code={\pgfkeys{/three point perspective/.cd,#1}},
perspective/.default={p={(15,0,0)},q={(0,15,0)},r={(0,0,50)}},
}
\tikzdeclarecoordinatesystem{three point perspective}{
\pgfkeys{/three point perspective/.cd,coordinate={#1}}
\pgfmathsetmacro\temp@p@w{\H@tpp@da*\tpp@x + \H@tpp@db*\tpp@y + \H@tpp@dc*\tpp@z + 1}
\pgfmathsetmacro\temp@p@x{(\H@tpp@aa*\tpp@x + \H@tpp@ab*\tpp@y + \H@tpp@ac*\tpp@z)/\temp@p@w}
\pgfmathsetmacro\temp@p@y{(\H@tpp@ba*\tpp@x + \H@tpp@bb*\tpp@y + \H@tpp@bc*\tpp@z)/\temp@p@w}
\pgfmathsetmacro\temp@p@z{(\H@tpp@ca*\tpp@x + \H@tpp@cb*\tpp@y + \H@tpp@cc*\tpp@z)/\temp@p@w}
\pgfpointxyz{\temp@p@x}{\temp@p@y}{\temp@p@z}
}
\tikzaliascoordinatesystem{tpp}{three point perspective}
\makeatother
\definecolor{mydarkbluishgray}{RGB}{134 134 191}
\definecolor{mylightbluishgray}{RGB}{215 215 255}
\begin{document}
\begin{tikzpicture}[line join=round]
\begin{scope}[
scale=10,
view={85}{-40},
perspective={
p = {(1,0,0.55)},
q = {(0,1,0.55)},
}
]
\fill[mydarkbluishgray] (tpp cs:0,0,0) -- (tpp cs:0,0,1) -- (tpp cs:0,0.5,1) -- (tpp cs:0,0.5,0) -- cycle;
\fill[mylightbluishgray] (tpp cs:0,0,0) -- (tpp cs:0,0,1) -- (tpp cs:1.5,0,1) -- (tpp cs:1.5,0,0) -- cycle;
\path (tpp cs:0,0,0.5) -- node[sloped]{OMEAG} (tpp cs:1.5,0,0.5);
\begin{scope}[dotted,line width=0.2pt]
\node[label=right:p,fill,circle,inner sep = 2pt] (p) at (vp-p){};
\draw (tpp cs:0,0,1) -- (p.center);
\draw (tpp cs:0,0,0) -- (p.center);
\draw (tpp cs:0,0.5,1) -- (p.center);
\draw (tpp cs:0,0.5,0) -- (p.center);
\node[label=left:q,fill,circle,inner sep = 2pt] (q) at (vp-q){};
\draw (tpp cs:0,0,1) -- (q.center);
\draw (tpp cs:0,0,0) -- (q.center);
\draw (tpp cs:1.5,0,1) -- (q.center);
\draw (tpp cs:1.5,0,0) -- (q.center);
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}
Of course I had to make an animation to show different vanishing point distances:
MWE animation:
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usepackage{mathtools}
\makeatletter
% Initialize H matrix for perspective view
\pgfmathsetmacro\H@tpp@aa{1}\pgfmathsetmacro\H@tpp@ab{0}\pgfmathsetmacro\H@tpp@ac{0}%\pgfmathsetmacro\H@tpp@ad{0}
\pgfmathsetmacro\H@tpp@ba{0}\pgfmathsetmacro\H@tpp@bb{1}\pgfmathsetmacro\H@tpp@bc{0}%\pgfmathsetmacro\H@tpp@bd{0}
\pgfmathsetmacro\H@tpp@ca{0}\pgfmathsetmacro\H@tpp@cb{0}\pgfmathsetmacro\H@tpp@cc{1}%\pgfmathsetmacro\H@tpp@cd{0}
\pgfmathsetmacro\H@tpp@da{0}\pgfmathsetmacro\H@tpp@db{0}\pgfmathsetmacro\H@tpp@dc{0}%\pgfmathsetmacro\H@tpp@dd{1}
%Initialize H matrix for main rotation
\pgfmathsetmacro\H@rot@aa{1}\pgfmathsetmacro\H@rot@ab{0}\pgfmathsetmacro\H@rot@ac{0}%\pgfmathsetmacro\H@rot@ad{0}
\pgfmathsetmacro\H@rot@ba{0}\pgfmathsetmacro\H@rot@bb{1}\pgfmathsetmacro\H@rot@bc{0}%\pgfmathsetmacro\H@rot@bd{0}
\pgfmathsetmacro\H@rot@ca{0}\pgfmathsetmacro\H@rot@cb{0}\pgfmathsetmacro\H@rot@cc{1}%\pgfmathsetmacro\H@rot@cd{0}
%\pgfmathsetmacro\H@rot@da{0}\pgfmathsetmacro\H@rot@db{0}\pgfmathsetmacro\H@rot@dc{0}\pgfmathsetmacro\H@rot@dd{1}
\pgfkeys{
/three point perspective/.cd,
p/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#1))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ba{#2/#1}
\pgfmathsetmacro\H@tpp@ca{#3/#1}
\pgfmathsetmacro\H@tpp@da{ 1/#1}
\coordinate (vp-p) at (#1,#2,#3);
\fi
},
q/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#2))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ab{#1/#2}
\pgfmathsetmacro\H@tpp@cb{#3/#2}
\pgfmathsetmacro\H@tpp@db{ 1/#2}
\coordinate (vp-q) at (#1,#2,#3);
\fi
},
r/.code args={(#1,#2,#3)}{
\pgfmathparse{int(round(#3))}
\ifnum\pgfmathresult=0\else
\pgfmathsetmacro\H@tpp@ac{#1/#3}
\pgfmathsetmacro\H@tpp@bc{#2/#3}
\pgfmathsetmacro\H@tpp@dc{ 1/#3}
\coordinate (vp-r) at (#1,#2,#3);
\fi
},
coordinate/.code args={#1,#2,#3}{
\def\tpp@x{#1}
\def\tpp@y{#2}
\def\tpp@z{#3}
},
}
\tikzset{
view/.code 2 args={
\pgfmathsetmacro\rot@main@theta{#1}
\pgfmathsetmacro\rot@main@phi{#2}
% Row 1
\pgfmathsetmacro\H@rot@aa{cos(\rot@main@phi)}
\pgfmathsetmacro\H@rot@ab{sin(\rot@main@phi)}
\pgfmathsetmacro\H@rot@ac{0}
% Row 2
\pgfmathsetmacro\H@rot@ba{-cos(\rot@main@theta)*sin(\rot@main@phi)}
\pgfmathsetmacro\H@rot@bb{cos(\rot@main@phi)*cos(\rot@main@theta)}
\pgfmathsetmacro\H@rot@bc{sin(\rot@main@theta)}
% Row 3
\pgfmathsetmacro\H@m@ca{sin(\rot@main@phi)*sin(\rot@main@theta)}
\pgfmathsetmacro\H@m@cb{-cos(\rot@main@phi)*sin(\rot@main@theta)}
\pgfmathsetmacro\H@m@cc{cos(\rot@main@theta)}
% Set vector values
\pgfmathsetmacro\vec@x@x{\H@rot@aa}
\pgfmathsetmacro\vec@y@x{\H@rot@ab}
\pgfmathsetmacro\vec@z@x{\H@rot@ac}
\pgfmathsetmacro\vec@x@y{\H@rot@ba}
\pgfmathsetmacro\vec@y@y{\H@rot@bb}
\pgfmathsetmacro\vec@z@y{\H@rot@bc}
% Set pgf vectors
\pgfsetxvec{\pgfpoint{\vec@x@x cm}{\vec@x@y cm}}
\pgfsetyvec{\pgfpoint{\vec@y@x cm}{\vec@y@y cm}}
\pgfsetzvec{\pgfpoint{\vec@z@x cm}{\vec@z@y cm}}
},
}
\tikzset{
perspective/.code={\pgfkeys{/three point perspective/.cd,#1}},
perspective/.default={p={(15,0,0)},q={(0,15,0)},r={(0,0,50)}},
}
\tikzdeclarecoordinatesystem{three point perspective}{
\pgfkeys{/three point perspective/.cd,coordinate={#1}}
\pgfmathsetmacro\temp@p@w{\H@tpp@da*\tpp@x + \H@tpp@db*\tpp@y + \H@tpp@dc*\tpp@z + 1}
\pgfmathsetmacro\temp@p@x{(\H@tpp@aa*\tpp@x + \H@tpp@ab*\tpp@y + \H@tpp@ac*\tpp@z)/\temp@p@w}
\pgfmathsetmacro\temp@p@y{(\H@tpp@ba*\tpp@x + \H@tpp@bb*\tpp@y + \H@tpp@bc*\tpp@z)/\temp@p@w}
\pgfmathsetmacro\temp@p@z{(\H@tpp@ca*\tpp@x + \H@tpp@cb*\tpp@y + \H@tpp@cc*\tpp@z)/\temp@p@w}
\pgfpointxyz{\temp@p@x}{\temp@p@y}{\temp@p@z}
}
\tikzaliascoordinatesystem{tpp}{three point perspective}
\makeatother
\definecolor{mydarkbluishgray}{RGB}{134 134 191}
\definecolor{mylightbluishgray}{RGB}{215 215 255}
\begin{document}
\foreach \vp in {1,1.1,...,5}{
% \foreach \vp in {1}{
\begin{tikzpicture}[line join=round]
\clip (-12,0) rectangle (12,10);
\begin{scope}[
scale=10,
view={85}{-40},
perspective={
p = {(\vp,0,0.55)},
q = {(0,\vp,0.55)},
}
]
\fill[mydarkbluishgray] (tpp cs:0,0,0) -- (tpp cs:0,0,1) -- (tpp cs:0,0.5,1) -- (tpp cs:0,0.5,0) -- cycle;
\fill[mylightbluishgray] (tpp cs:0,0,0) -- (tpp cs:0,0,1) -- (tpp cs:1.5,0,1) -- (tpp cs:1.5,0,0) -- cycle;
\path[dotted] (tpp cs:0,0,0.5) -- node[sloped]{OMEAG} (tpp cs:1.5,0,0.5);
\begin{scope}[dotted,line width=0.2pt]
\node[label=right:p,fill,circle,inner sep = 2pt] (p) at (vp-p){};
\draw (tpp cs:0,0,1) -- (p.center);
\draw (tpp cs:0,0,0) -- (p.center);
\draw (tpp cs:0,0.5,1) -- (p.center);
\draw (tpp cs:0,0.5,0) -- (p.center);
\node[label=left:q,fill,circle,inner sep = 2pt] (q) at (vp-q){};
\draw (tpp cs:0,0,1) -- (q.center);
\draw (tpp cs:0,0,0) -- (q.center);
\draw (tpp cs:1.5,0,1) -- (q.center);
\draw (tpp cs:1.5,0,0) -- (q.center);
\end{scope}
\end{scope}
\end{tikzpicture}
}
\end{document}
Appendix: Two point perspective theory
A perspective transformation with two vanishing points can be described with a four by four transformation matrix H which is a function of the two vanishing points p with p_x <> 0
, and r with r_y <> 0
.
You can build H as follows
To be able to transform a point x expressed in 3D with H, it must be expressed in a projected space, which can be written as
Any multiplication (elongation of the 4D vector) of a vector in projected space with a non-zero scalar alpha, still maps to the same point in 3D space. E.g., the following two points map to the same point in 3D space:
So to get the three coordinates of the 3D point, you can divide all entries by the fourth entry (we need this after multiplication with a transformation matrix as H).