diff --git a/présentation.tex b/présentation.tex index 211a820..0e4a671 100644 --- a/présentation.tex +++ b/présentation.tex @@ -18,7 +18,7 @@ \usetheme{Frankfurt} \usepackage{graphicx} -% \title{FMIN313 Moteurs de jeux\\ Génération de terrains} +\title{FMIN313 Moteurs de jeux\\ Génération de terrains} \author{DUPÉRON Georges \and\texorpdfstring{\\}{} BONAVERO Yoann} \institute{Université Montpellier II,\\Département informatique\\Master 2 IFPRU\\Encadrants~: F. Koriche et M. Moulis} \date{Lundi 14 novembre 2011} @@ -58,6 +58,11 @@ \xdef\noiseseed{\pgfmathresult} \makeatletter +\def\getcache#1{\csname cache,#1\endcsname} +\def\setcache#1#2{\expandafter\xdef\csname cache,#1\endcsname{#2}} +\def\clearcache#1{\expandafter\global\expandafter\let\csname cache,#1\endcsname\@undefined} +\def\setintmacro#1#2{\pgfmathparse{int(#2)}\edef#1{\pgfmathresult}} +% \pgfmathdeclarefunction{lazyifthenelse}{3}{% \ifx 1#1% \pgfmathparse{#2}% @@ -96,6 +101,18 @@ % Craters sqdistance_(\dx,\dy)=\dx*\dx+\dy*\dy; sqdistance(\x,\y,\cx,\cy)=sqdistance_(\x-\cx,\y-\cy); + % 2D Perlin + noise2D(\x,\y,\octave)=hash(\x,hash(\y,hash(\octave,\noiseseed))); + sampleLeftAbove2D(\x,\y,\periode,\octave)=noise2D(floor(\x/\periode), floor(\y/\periode) + 1, \octave); + sampleLeftBelow2D(\x,\y,\periode,\octave)=noise2D(floor(\x/\periode), floor(\y/\periode), \octave); + sampleRightAbove2D(\x,\y,\periode,\octave)=noise2D(floor(\x/\periode)+1, floor(\y/\periode) + 1, \octave); + sampleRightBelow2D(\x,\y,\periode,\octave)=noise2D(floor(\x/\periode)+1, floor(\y/\periode), \octave); + octave2DCosine(\x,\y,\octave,\periode,\amplitude)=\amplitude*cosineInterpolation(sampleDelta(\y,\periode), + cosineInterpolation(sampleDelta(\x,\periode), sampleLeftBelow2D(\x,\y,\periode,\octave), sampleRightBelow2D(\x,\y,\periode,\octave)), + cosineInterpolation(sampleDelta(\x,\periode), sampleLeftAbove2D(\x,\y,\periode,\octave), sampleRightAbove2D(\x,\y,\periode,\octave)) + ); + perlin2DCosine_(\x,\y,\octave,\periode,\octaves,\persistance,\amplitude)=lazyifthenelse(\octave >= \octaves, 0, "octave2DCosine(\x,\y,\octave,\periode,\amplitude) + perlin2DCosine_(\x,\y,\octave+1,\periode*0.5,\octaves,\persistance,\amplitude*\persistance)"); + perlin2DCosine(\x,\y,\periode,\octaves,\persistance,\amplitude)=perlin2DCosine_(\x,\y,0,\periode,\octaves,\persistance,\amplitude); } } \shorthandon{;?:} @@ -206,21 +223,135 @@ \begin{frame} \frametitle{Perlin noise (Variations)} \begin{itemize} - \item Cavernes, nuages, textures, terrains : bruit $n$D et voxels. - \item Ridged Perlin Noise. - \item Midpoint displacement. - \item Simplex noise : généralisation des triangles équilatéraux à $n$ dimensions, interpolation par rapport aux coins. $d^2$ au lieu de $2^d$. - \item Bruit répétable 1D : points sur un cercle dans un espace 2D. Généralisation à $n$ dimensions : hypercercle $n$D dans un espace $2n$D. + \item<1-> Cavernes, nuages\only<2->{, textures, terrains : bruit $n$D et voxels.} + \only<1>{ + \begin{figure}[h] + \centering + \begin{tikzpicture}[scale=0.025] + \xdef\twodperlinsize{128} + \xdef\maxvtwodperlin{0} + \xdef\minvtwodperlin{0} + \def\maxradius{32} + \def\ncircles{10} + \foreach \y in {1,2,...,\twodperlinsize}{ + \message{Perlin 2D line \y/\twodperlinsize.} + \foreach \x in {1,2,...,\twodperlinsize}{ + \pgfmathsetmacro{\v}{-perlin2DCosine(\x,\y,16,3,0.5,50} + \setcache{vtwodperlin,\x,\y}{\v} + \pgfmathparse{max(\maxvtwodperlin,\v)} + \xdef\maxvtwodperlin{\pgfmathresult} + \pgfmathparse{min(\minvtwodperlin,\v)} + \xdef\minvtwodperlin{\pgfmathresult} + } + } + \definecolor{gradientpoint0}{rgb}{0,0,1} + \definecolor{gradientpoint1}{rgb}{0,0.3,1} + \definecolor{gradientpoint2}{rgb}{0.3,0.3,1} + \definecolor{gradientpoint3}{rgb}{1,1,1} + \def\positions{{0,0.1,0.9,1}} + \foreach \y in {1,2,...,\twodperlinsize}{ + \message{Gradient line \y/\twodperlinsize...} + \foreach \x in {1,2,...,\twodperlinsize}{ + \pgfmathsetmacro{\v}{(\getcache{vtwodperlin,\x,\y}-\minvtwodperlin)/max(1,\maxvtwodperlin-\minvtwodperlin)} + \pgfmathsetmacro{\v}{max(0,min(1,\v))} + \foreach \pointb in {1,...,3}{ + \pgfmathsetmacro{\posb}{\positions[\pointb]} + \pgfmathparse{\v <= \posb} + \ifnum 1=\pgfmathresult + \setintmacro{\pointa}{\pointb-1} + \pgfmathsetmacro{\posa}{\positions[\pointa]} + \pgfmathsetmacro{\mix}{100 - 100 * (\v-\posa) / (\posb-\posa)} + \xdef\colora{gradientpoint\pointa} + \xdef\colorb{gradientpoint\pointb} + \xdef\mix{\mix} + \breakforeach + \fi + } + \path[fill=\colora!\mix!\colorb] (\x,\y) rectangle ++(1.5,1.5); + } + } + \end{tikzpicture} + \end{figure} + } + \only<2>{ + \begin{figure}[h] + \centering + \begin{tikzpicture}[scale=0.025] + \definecolor{gradientpoint0}{rgb}{0,0,0.5} + \definecolor{gradientpoint1}{rgb}{0.2,0.2,1} + \definecolor{gradientpoint2}{rgb}{0.9,0.6,0.1} + \definecolor{gradientpoint3}{rgb}{0.1,0.6,0.2} + \definecolor{gradientpoint4}{rgb}{0.6,0.3,0.05} + \definecolor{gradientpoint5}{rgb}{1,1,1} + \def\positions{{0,0.3,0.4,0.88,0.94,1}} + \foreach \y in {1,2,...,\twodperlinsize}{ + \message{Gradient line \y/\twodperlinsize...} + \foreach \x in {1,2,...,\twodperlinsize}{ + \pgfmathsetmacro{\v}{(\getcache{vtwodperlin,\x,\y}-\minvtwodperlin)/max(1,\maxvtwodperlin-\minvtwodperlin)} + \pgfmathsetmacro{\v}{max(0,min(1,\v))} + \foreach \pointb in {1,...,5}{ + \pgfmathsetmacro{\posb}{\positions[\pointb]} + \pgfmathparse{\v <= \posb} + \ifnum 1=\pgfmathresult + \setintmacro{\pointa}{\pointb-1} + \pgfmathsetmacro{\posa}{\positions[\pointa]} + \pgfmathsetmacro{\mix}{100 - 100 * (\v-\posa) / (\posb-\posa)} + \xdef\colora{gradientpoint\pointa} + \xdef\colorb{gradientpoint\pointb} + \xdef\mix{\mix} + \breakforeach + \fi + } + \path[fill=\colora!\mix!\colorb] (\x,\y) rectangle ++(1.5,1.5); + } + } + \end{tikzpicture} + \end{figure} + } + \item<3-> Ridged Perlin Noise. + \only<3>{ + \begin{figure}[h] + \centering + \begin{tikzpicture}[scale=0.025] + \definecolor{gradientpoint0}{rgb}{0,0,0.5} + \definecolor{gradientpoint1}{rgb}{0.2,0.2,1} + \definecolor{gradientpoint2}{rgb}{0.9,0.6,0.1} + \definecolor{gradientpoint3}{rgb}{0.1,0.6,0.2} + \definecolor{gradientpoint4}{rgb}{0.6,0.3,0.05} + \definecolor{gradientpoint5}{rgb}{1,1,1} + \def\positions{{0,0.3,0.4,0.88,0.94,1}} + \foreach \y in {1,2,...,\twodperlinsize}{ + \message{Gradient line \y/\twodperlinsize...} + \foreach \x in {1,2,...,\twodperlinsize}{ + \pgfmathsetmacro{\v}{(\getcache{vtwodperlin,\x,\y}-\minvtwodperlin)/max(1,\maxvtwodperlin-\minvtwodperlin)} + \pgfmathsetmacro{\v}{max(0,min(1,\v))} + \pgfmathsetmacro{\v}{abs(\v-0.5)*2} + \foreach \pointb in {1,...,5}{ + \pgfmathsetmacro{\posb}{\positions[\pointb]} + \pgfmathparse{\v <= \posb} + \ifnum 1=\pgfmathresult + \setintmacro{\pointa}{\pointb-1} + \pgfmathsetmacro{\posa}{\positions[\pointa]} + \pgfmathsetmacro{\mix}{100 - 100 * (\v-\posa) / (\posb-\posa)} + \xdef\colora{gradientpoint\pointa} + \xdef\colorb{gradientpoint\pointb} + \xdef\mix{\mix} + \breakforeach + \fi + } + \path[fill=\colora!\mix!\colorb] (\x,\y) rectangle ++(1.5,1.5); + } + } + \end{tikzpicture} + \end{figure} + } + \item<4-> Midpoint displacement. + \item<5-> Simplex noise : généralisation des triangles équilatéraux à $n$ dimensions, interpolation par rapport aux coins. $d^2$ au lieu de $2^d$. + \item<6-> Bruit répétable 1D : points sur un cercle dans un espace 2D. Généralisation à $n$ dimensions : hypercercle $n$D dans un espace $2n$D. {\tiny\url{http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/}} \end{itemize} \end{frame} -\makeatletter -\def\getcache#1{\csname cache,#1\endcsname} -\def\setcache#1#2{\expandafter\xdef\csname cache,#1\endcsname{#2}} -\def\clearcache#1{\expandafter\global\expandafter\let\csname cache,#1\endcsname\@undefined} -\def\setintmacro#1#2{\pgfmathparse{int(#2)}\edef#1{\pgfmathresult}} -\makeatother \subsection{Craters et Hills Algorithm} \begin{frame} \frametitle{Craters et Hills Algorithm} @@ -233,13 +364,14 @@ \begin{figure}[h] \centering \begin{tikzpicture}[scale=0.025] - \def\craterssize{128} - \xdef\maxv{0} + \xdef\craterssize{128} + \xdef\maxvcraters{0} + \xdef\minvcraters{0} \def\maxradius{32} - \def\ncircles{50} + \def\ncircles{100} \foreach \y in {1,2,...,\craterssize}{ \foreach \x in {1,2,...,\craterssize}{ - \setcache{v,\x,\y}{0} + \setcache{vcraters,\x,\y}{0} } } \foreach \c in {1,...,\ncircles}{ @@ -255,27 +387,30 @@ \setintmacro{\x}{\circlex+\dx} \pgfmathparse{(\x > 0) && (\x <= \craterssize)} \ifnum 1=\pgfmathresult - \xdef\oldv{\getcache{v,\x,\y}} - \pgfmathparse{\oldv+max(0,\circler*\circler - (\dx*\dx + \dy*\dy))} - \setcache{v,\x,\y}{\pgfmathresult} - \pgfmathparse{max(\maxv,\pgfmathresult)} - \xdef\maxv{\pgfmathresult} + \xdef\oldv{\getcache{vcraters,\x,\y}} + \pgfmathsetmacro{\v}{\oldv - max(0,\circler - ((\dx*\dx + \dy*\dy)/\circler))} + \setcache{vcraters,\x,\y}{\v} + \pgfmathparse{max(\maxvcraters,\v)} + \xdef\maxvcraters{\pgfmathresult} + \pgfmathparse{min(\minvcraters,\v)} + \xdef\minvcraters{\pgfmathresult} \fi } \fi } } + \definecolor{gradientpoint0}{rgb}{0,0,0.5} + \definecolor{gradientpoint1}{rgb}{0.2,0.2,1} + \definecolor{gradientpoint2}{rgb}{0.9,0.6,0.1} + \definecolor{gradientpoint3}{rgb}{0.1,0.6,0.2} + \definecolor{gradientpoint4}{rgb}{0.6,0.3,0.05} + \definecolor{gradientpoint5}{rgb}{1,1,1} + \def\positions{{0,0.3,0.4,0.88,0.94,1}} \foreach \y in {1,2,...,\craterssize}{ \message{Gradient line \y/\craterssize...} \foreach \x in {1,2,...,\craterssize}{ - \pgfmathsetmacro{\v}{\getcache{v,\x,\y}/\maxv} - \definecolor{gradientpoint0}{rgb}{0,0,0.5} - \definecolor{gradientpoint1}{rgb}{0.2,0.2,1} - \definecolor{gradientpoint2}{rgb}{0.9,0.6,0.1} - \definecolor{gradientpoint3}{rgb}{0.1,0.6,0.2} - \definecolor{gradientpoint4}{rgb}{0.6,0.3,0.05} - \definecolor{gradientpoint5}{rgb}{1,1,1} - \def\positions{{0,0.3,0.4,0.88,0.94,1}} + \pgfmathsetmacro{\v}{(\getcache{vcraters,\x,\y}-\minvcraters)/max(1,\maxvcraters-\minvcraters)} + \pgfmathsetmacro{\v}{max(0,min(1,\v))} \foreach \pointb in {1,...,5}{ \pgfmathsetmacro{\posb}{\positions[\pointb]} \pgfmathparse{\v < \posb} @@ -289,8 +424,7 @@ \breakforeach \fi } - \path[fill=\colora!\mix!\colorb] (\x,\y) rectangle ++(1.2,1.2); - \clearcache{v,\x,\y} + \path[fill=\colora!\mix!\colorb] (\x,\y) rectangle ++(1.5,1.5); } } \end{tikzpicture} @@ -298,14 +432,114 @@ } \item<3-> Sur un terrain existant \only<3>{ - % TODO + \begin{figure}[h] + \centering + \begin{tikzpicture}[scale=0.025] + \xdef\cratersperlinsize{\twodperlinsize} + \xdef\maxvcratersperlin{\maxvtwodperlin} + \xdef\minvcratersperlin{\minvtwodperlin} + \def\maxradius{32} + \def\ncircles{20} + \foreach \y in {1,2,...,\cratersperlinsize}{ + \foreach \x in {1,2,...,\cratersperlinsize}{ + \setcache{vcratersperlin,\x,\y}{\getcache{vtwodperlin,\x,\y}} + } + } + \foreach \c in {1,...,\ncircles}{ + \setintmacro{\circlex}{noise1D(\c,0)*\cratersperlinsize} + \setintmacro{\circley}{noise1D(\c,1)*\cratersperlinsize} + \setintmacro{\circler}{noise1D(\c,2)*\maxradius} + \message{Circle number \c/\ncircles, center (\circlex, \circley), radius \circler} + \foreach \dy in {-\circler,...,\circler}{ + \setintmacro{\y}{\circley+\dy} + \pgfmathparse{(\y > 0) && (\y <= \cratersperlinsize)} + \ifnum 1=\pgfmathresult + \foreach \dx in {-\circler,...,\circler}{ + \setintmacro{\x}{\circlex+\dx} + \pgfmathparse{(\x > 0) && (\x <= \cratersperlinsize)} + \ifnum 1=\pgfmathresult + \xdef\oldv{\getcache{vcratersperlin,\x,\y}} + \pgfmathparse{\oldv - max(0,\circler - ((\dx*\dx + \dy*\dy)/\circler))} + \setcache{vcratersperlin,\x,\y}{\pgfmathresult} + \pgfmathparse{max(\maxvcratersperlin,\pgfmathresult)} + \xdef\maxvcratersperlin{\pgfmathresult} + \pgfmathparse{min(\minvcratersperlin,\pgfmathresult)} + \xdef\minvcratersperlin{\pgfmathresult} + \fi + } + \fi + } + } + \definecolor{gradientpoint0}{rgb}{0,0,0.5} + \definecolor{gradientpoint1}{rgb}{0.2,0.2,1} + \definecolor{gradientpoint2}{rgb}{0.9,0.6,0.1} + \definecolor{gradientpoint3}{rgb}{0.1,0.6,0.2} + \definecolor{gradientpoint4}{rgb}{0.6,0.3,0.05} + \definecolor{gradientpoint5}{rgb}{1,1,1} + \def\positions{{0,0.3,0.4,0.88,0.94,1}} + \foreach \y in {1,2,...,\cratersperlinsize}{ + \message{Gradient line \y/\cratersperlinsize...} + \foreach \x in {1,2,...,\cratersperlinsize}{ + \pgfmathsetmacro{\v}{(\getcache{vcratersperlin,\x,\y}-\minvcratersperlin)/max(1,\maxvcratersperlin-\minvcratersperlin)} + \pgfmathsetmacro{\v}{max(0,min(1,\v))} + \foreach \pointb in {1,...,5}{ + \pgfmathsetmacro{\posb}{\positions[\pointb]} + \pgfmathparse{\v <= \posb} + \ifnum 1=\pgfmathresult + \setintmacro{\pointa}{\pointb-1} + \pgfmathsetmacro{\posa}{\positions[\pointa]} + \pgfmathsetmacro{\mix}{100 - 100 * (\v-\posa) / (\posb-\posa)} + \xdef\colora{gradientpoint\pointa} + \xdef\colorb{gradientpoint\pointb} + \xdef\mix{\mix} + \breakforeach + \fi + } + \path[fill=\colora!\mix!\colorb] (\x,\y) rectangle ++(1.5,1.5); + } + } + \end{tikzpicture} + \end{figure} } \end{itemize} - \item<4-> Hills Algorithm - \begin{itemize} - \item Inverse de craters : on ajoute plein de cercles - \end{itemize} - \item<5-> Stockage des cercles dans un arbre (BSP, Quadtree, arbre du LOD, \dots{}). + \item<4-> Hills Algorithm~: ajouter des cercles + \only<4>{ + \begin{figure}[h] + \centering + \begin{tikzpicture}[scale=0.025] + \definecolor{gradientpoint0}{rgb}{0,0,0.5} + \definecolor{gradientpoint1}{rgb}{0.2,0.2,1} + \definecolor{gradientpoint2}{rgb}{0.9,0.6,0.1} + \definecolor{gradientpoint3}{rgb}{0.1,0.6,0.2} + \definecolor{gradientpoint4}{rgb}{0.6,0.3,0.05} + \definecolor{gradientpoint5}{rgb}{1,1,1} + \def\positions{{0,0.3,0.4,0.88,0.94,1}} + \foreach \y in {1,2,...,\craterssize}{ + \message{Gradient line \y/\craterssize...} + \foreach \x in {1,2,...,\craterssize}{ + \pgfmathsetmacro{\v}{(\getcache{vcraters,\x,\y}-\minvcraters)/max(1,\maxvcraters-\minvcraters)} + \pgfmathsetmacro{\v}{max(0,min(1,\v))} + \pgfmathsetmacro{\v}{1-\v} + \foreach \pointb in {1,...,5}{ + \pgfmathsetmacro{\posb}{\positions[\pointb]} + \pgfmathparse{\v < \posb} + \ifnum 1=\pgfmathresult + \setintmacro{\pointa}{\pointb-1} + \pgfmathsetmacro{\posa}{\positions[\pointa]} + \pgfmathsetmacro{\mix}{100 - 100 * (\v-\posa) / (\posb-\posa)} + \xdef\colora{gradientpoint\pointa} + \xdef\colorb{gradientpoint\pointb} + \xdef\mix{\mix} + \breakforeach + \fi + } + \path[fill=\colora!\mix!\colorb] (\x,\y) rectangle ++(1.5,1.5); + } + } + \end{tikzpicture} + \end{figure} + } + \item<5-> Stockage des cercles dans un arbre (BSP, Quadtree, LOD, \dots{}). \end{itemize} \end{frame}