-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathlyapunov.osl
135 lines (108 loc) · 3.47 KB
/
lyapunov.osl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* Lyapunov Shader - in memory of great mathematician Aleksandr Mikhailovich Lyapunov
* Original code: Sylvio Sell - maitag.de - Rostock Germany 2013
* recoded 2015 for better node integration and artists control
* devel task: https://developer.blender.org/T32305
* thanks to Thomas Dinges for initial OSL port
*/
/* ------- function that describes behavior of dynamic system ------- */
float func(float x, float p, float p1, float p2)
{
return p1*sin(x+p)*sin(x+p)+p2;
}
float deriv(float x, float p, float p1, float p2)
{
return p1*sin(2.0*(x+p));
}
/* ------- sequence (todo: customizing by parameter;) ------- */
void pre_step(output float x, point p, float p1, float p2)
{
for(int i = 0; i < 3; i++) {
x = func(x,p[i],p1,p2);
}
}
void main_step(output float index, output int iter, output float x, point p, float p1, float p2, float balance)
{
for(int i = 0; i < 3; i++) {
x = func(x,p[i],p1,p2);
index += ( log(fabs(deriv(x,p[i],p1,p2)))*balance + deriv(x,p[i],p1,p2)*(1.0-balance) ) / 2.0;
iter++;
}
}
/* ------- calculates Lyapunov index ------- */
float lyapunov(point p, float x_start, float iteration_pre, float iteration_main, float p1, float p2, float balance)
{
float x = x_start;
int iter_pre = (int)floor(iteration_pre);
int iter_main = (int)floor(iteration_main);
float nabla_pre = iteration_pre - (float)iter_pre;
float nabla_main = iteration_main - (float)iter_main;
float index = 0.0;
float ableitung = 0.0;
int iter = 0;
/* Pre-iteration */
for(int i = 0; i < iter_pre; i++) {
pre_step(x,p,p1,p2);
}
if (nabla_pre != 0.0) {
float x_pre = x;
pre_step(x,p,p1,p2);
x = x*nabla_pre + x_pre*(1.0-nabla_pre);
}
/* Main-iteration */
for(int i = 0; i < iter_main; i++) {
main_step(index, iter, x, p, p1, p2, balance);
}
if (nabla_main == 0.0) {
index = (iter != 0) ? index/(float)(iter) : 0.0;
}
else {
float index_pre = (iter != 0) ? index/(float)(iter) : 0.0;
main_step(index, iter, x, p, p1, p2, balance);
index = (iter != 0) ? index/(float)(iter) : 0.0;
index = index*nabla_main + index_pre*(1.0-nabla_main);
}
return index;
}
/* ------------------ SHADER MAIN ---------------------- */
shader node_lyapunov(
float Shift = 0.0,
float Balance = 0.0,
float Pre_Iteration = 0.0,
float Main_Iteration = 1.0,
float Param1 = 2.0,
float Param2 = 2.0,
float Scale = 1.0,
point Pos = P,
output float Fac = 0.0,
output float Positiv = 0.0,
output float Negativ = 0.0)
{
/* Calculate Lyapunov Index */
float index = lyapunov(Pos*Scale, Shift, Pre_Iteration, Main_Iteration, Param1, Param2, Balance);
/* separate output */
if (index > 0.0) {
Positiv = index;
}
else {
Negativ = -index;
}
Fac = 0.5 + index;
}