Aligning a text in 3d diagram
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 inx
direction, to turn of setp_x
to 0.q={(q_x,q_y,q_z)}
to set the vanishing point iny
direction, to turn of setq_y
to 0.r={(r_x,r_y,r_z)}
to set the vanishing point inz
direction, to turn of setr_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).
When I saw Max's nice answer I could not resist to add some decorations.text
effects. @Max : if you want to append this to your answer, I will be happy to delete this. The result is also not quite perfect since the individual characters do get rescaled, but not the different sides of the characters.
EDIT: Even though the rescaling of the heights was OK (I think) in my previous version, I did not properly stretch the widths of the characters. Therefore, the effect was weaker than it should be. Big thanks to AndreC for bringing me on the right (?) track!
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usetikzlibrary{decorations.text,calc,math}
\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) -- (tpp cs:1.5,0,0.5)
node[sloped,midway,opacity=0](TEXT){~~Ducks, marmots and koala bears!~} ;
% text effects1
\draw let \p1=($(tpp cs:1.5,0,0.5)-(tpp cs:0,0,0.5)$), % x
\p2=($(tpp cs:0,0,1)-(tpp cs:0,0,0)$), % z @ x=0
\p3=($(tpp cs:1.5,0,1)-(tpp cs:1.5,0,0)$), % z @ x=1.5
\n1={\y3/\y2},\n2={\x1/\y2} % n1 : decrease in z
in
\pgfextra{\pgfmathsetmacro{\RatioOne}{\n1}\xdef\RatioOne{\RatioOne}
\pgfmathsetmacro{\RatioTwo}{\n2}\xdef\RatioTwo{\RatioTwo}
\typeout{\RatioOne,\RatioTwo}}
[decorate,decoration={text effects along path, text={Ducks, marmots and koala bears!},raise=-3pt,
text effects/.cd,
character count=\i, character total=\n,
characters={text along path,
xscale=\RatioOne*1.15,
yscale=1.15*((1.5-0.5*\RatioTwo)-(\i/\n)*(1-\RatioTwo))}}]
(tpp cs:0.2,0,0.5) -- (tpp cs:1.5,0,0.5);
\draw (tpp cs:1,0,1) -- (tpp cs:1,0,0);
%
\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}
\documentclass{article}
\usepackage{pst-solides3d}
\begin{document}
\psset{viewpoint=50 20 30 rtp2xyz,Decran=50}
\begin{pspicture}(-4,-4)(4,5)
\psset{unit=0.5,solidmemory,lightsrc=viewpoint}
\psSolid[object=cube,a=8,action=draw**,name=A,linecolor=red]%
\psset{fontsize=80}
\psSolid[object=plan,action=none, definition=solidface,args=A 0,name=P0]
\psProjection[object=texte,linecolor=red,text=Side A,plan=P0]%
\psSolid[object=plan,action=none,definition=solidface,args=A 1,name=P1]
\psProjection[object=texte,linecolor=red,text=Side B,plan=P1]%
\psSolid[object=plan,action=none,definition=solidface,args=A 4,name=P4]
\psProjection[object=texte,linecolor=red,text=Side E,plan=P4]%
\axesIIID(4,4,4)(6,6,6)
\end{pspicture}
\end{document}