January 15, 2021, 06:01:35 PM

### Author Topic: [bmx] Interpolation library by Bobysait [ 7 months ago ]  (Read 709 times)

#### BlitzBot

• Jr. Member
• Posts: 1
##### [bmx] Interpolation library by Bobysait [ 7 months ago ]
« on: June 29, 2017, 12:28:42 AM »
Title : Interpolation library
Author : Bobysait
Posted : 7 months ago

Description : Here is a library to create interpolation between arrays of objects
there is already 2 extensions for Int[] and Float[]
You can create your own "interpolator" for Vector or any kind of objects
you'll need to implement a method for the lowest interpolation
Code: [Select]
`Method Interpolate:Object(a:Object,b:Object, v:Double) Abstract`
See the extended types for more details (they use linear interpolation, but they can be replaced by cos/sin/square interpolation etc ...)

-> use it as standalone include :
save the file and include it ...

-> use it as a module :
Add "Module yourname.interpolation" at the top of the file and save it to "interpolation.bmx" in a "yourname.mod" folder in your blitzmax mod's folder to build it as a module
Then just import it -> Import yourname.interpolation

The sample will show an interpolation of 3 levels of arrays
using color templates for Season, time of the day and altitude of the sky.
Code: [Select]
`' ***************************************************************' * SAMPLE *' *************************************************************** ' Smart function to convert Int32 RGB to an Int32[4] ([R,G,B,A] -> alpha filled with "255") Function IToI4:Int[](l:Long, a:Long=\$FF) Local c:Int = l + a Shl(24); Return [c Shr(16) & \$FF,c Shr(8) & \$FF,c & \$FF, c Shr(24) & \$FF]; End Function Graphics 800,600,0,0 ' - 3 dimensions gradient ' season - Night/Sunrise/Sun/Sunset - Emissive/Diffuse/Specular/Refraction/Ambient Local grd:Int4Gradient3 = Int4Gradient3.Create(5,5,5); ' Winter - Emissive - Diffuse - Specular - Refraction - Ambient grd.Gradient(0,0).SetArray( [ IToI4(\$000000), IToI4(\$020202), IToI4(\$051015), IToI4(\$041014), IToI4(\$0a101a) ] ); ' night grd.Gradient(0,1).SetArray( [ IToI4(\$171a24), IToI4(\$d08040), IToI4(\$b08050), IToI4(\$607080), IToI4(\$204060) ] ); ' sunrise grd.Gradient(0,2).SetArray( [ IToI4(\$101217), IToI4(\$ecddc7), IToI4(\$cddbfc), IToI4(\$6090c0), IToI4(\$204060) ] ); ' day grd.Gradient(0,3).SetArray( [ IToI4(\$181d23), IToI4(\$a06080), IToI4(\$906030), IToI4(\$80a0b0), IToI4(\$304080) ] ); ' sunset grd.Gradient(0,4).SetArray( grd.Gradient(0,4).Objects ); ' copy first to last -> cyclic ' Springtime grd.Gradient(1,0).SetArray( [ IToI4(\$000000), IToI4(\$01080c), IToI4(\$070e17), IToI4(\$0a161e), IToI4(\$081924) ] ); grd.Gradient(1,1).SetArray( [ IToI4(\$01080c), IToI4(\$e0a507), IToI4(\$c165ba), IToI4(\$5c267b), IToI4(\$23083f) ] ); grd.Gradient(1,2).SetArray( [ IToI4(\$212529), IToI4(\$bce1e2), IToI4(\$105b73), IToI4(\$02316c), IToI4(\$000764) ] ); grd.Gradient(1,3).SetArray( [ IToI4(\$000000), IToI4(\$d34608), IToI4(\$d846a6), IToI4(\$55218e), IToI4(\$1b1057) ] ); grd.Gradient(1,4).SetArray( grd.Gradient(1,4).Objects ); ' Summer grd.Gradient(2,0).SetArray( [ IToI4(\$000000), IToI4(\$01080c), IToI4(\$070e17), IToI4(\$0a161e), IToI4(\$081924) ] ); grd.Gradient(2,1).SetArray( [ IToI4(\$01080c), IToI4(\$e0a507), IToI4(\$c165ba), IToI4(\$5c267b), IToI4(\$23083f) ] ); grd.Gradient(2,2).SetArray( [ IToI4(\$212529), IToI4(\$e8f0ff), IToI4(\$306070), IToI4(\$013070), IToI4(\$002050) ] ); grd.Gradient(2,3).SetArray( [ IToI4(\$000000), IToI4(\$d04010), IToI4(\$d840a0), IToI4(\$502090), IToI4(\$201050) ] ); grd.Gradient(2,4).SetArray( grd.Gradient(2,4).Objects ); ' Automn grd.Gradient(3,0).SetArray( [ IToI4(\$000000), IToI4(\$01080c), IToI4(\$070e17), IToI4(\$0a161e), IToI4(\$081924) ] ); grd.Gradient(3,1).SetArray( [ IToI4(\$01080c), IToI4(\$e0d5c7), IToI4(\$c1959a), IToI4(\$5c265b), IToI4(\$401040) ] ); grd.Gradient(3,2).SetArray( [ IToI4(\$212529), IToI4(\$dce1e2), IToI4(\$405b63), IToI4(\$12415c), IToI4(\$103754) ] ); grd.Gradient(3,3).SetArray( [ IToI4(\$000000), IToI4(\$d3c608), IToI4(\$d88636), IToI4(\$65413e), IToI4(\$4b2017) ] ); grd.Gradient(3,4).SetArray( grd.Gradient(3,4).Objects ); ' cycle season grd.Gradient(4,0).SetArray( grd.Gradient(0,0).Objects ); grd.Gradient(4,1).SetArray( grd.Gradient(0,1).Objects ); grd.Gradient(4,2).SetArray( grd.Gradient(0,2).Objects ); grd.Gradient(4,3).SetArray( grd.Gradient(0,3).Objects ); grd.Gradient(4,4).SetArray( grd.Gradient(0,4).Objects ); Local day:int = 100 Local hour:Int = 8 Local update:Byte = True; Repeat If MouseDown(1) If MouseX()>300 And MouseX()<300+365 If MouseY()>10 And MouseY()<170 day = MouseX()-300 hour = Float(1 - Float(MouseY()-10)/160) * 24 Update = True EndIf EndIf EndIf If update Cls() SetColor 100,100,100 DrawRect 300,10,365,160 SetColor 255,100,100 DrawLine 300,5,300,170 DrawLine 300,170,670,170 SetColor 255,255,000 DrawLine 300+day, 170, 300+day, 170-hour*170/24 DrawLine 300, 170-hour*170/24, 300+day, 170-hour*170/24 Local v:Float; For v = 0 To 160 Local a:Int[] = grd.Get(Float(day)/365, Float(hour)/24, v/160); SetColor a[0],a[1],a[2] DrawRect 10,170-v,200,1 Next SetColor 255,255,255 DrawText "Day : "+day+" hour : "+hour, 10, 190 DrawText "Days", 650, 190 DrawText "Hours ", 220, 10 Flip True update = False EndIf; Until KeyDown(KEY_ESCAPE) End`

Code :
Code: BlitzMax
1. SuperStrict
2.
3. Rem
4. undocument the @Module line to build as a module.
6. EndRem
7.
9.
10. ' Abstract type ! Don't create instance of BGradient without extending it first !
13.
14.         Field Objects:Object[];
15.
16.         Method Interpolate:Object(a:Object,b:Object, v:Double) Abstract
17.
18.         Method NewInstance:Object() Abstract
19.
21.                 Self.Objects = New Object[Size];
22.                 Local i:Int; For i=0 Until Size; Self.Objects[i] = Self.NewInstance(); Next;
23.                 Return Self;
24.         End Method
25.
27.                 Self.Objects = array;
28.                 Return Self;
29.         End Method
30.
32.                 If (id<0 Or id>=Self.Objects.Length) Then Return Self;
33.                 Self.Objects[id] = o;
34.                 Return Self;
35.         End Method
36.
37.         Method Get:Object(v:Double)
38.                 If (v<=0) Then Return Self.Objects[0];
39.                 If (v>=1.0) Then Return Self.Objects[Self.Objects.Length-1];
40.                 Local i:Double = v * (Self.Objects.Length-1), i0:Int = Floor(i); If (i0=i) Then Return  Self.Objects[i0];
41.                 Return  Self.Interpolate (Self.Objects[i0], Self.Objects[i0+1], i-i0);
42.         End Method
43. End Type
44.
47.
49.
52.                 Local i:Int; For i=0 Until SizeI; Self.Gradients[i]=Self.NewInstance(SizeJ); Next;
53.                 Return Self;
54.         End Method
55.
56.         Method Get:Object(x:Double, y:Double)
57.                 If (x<=0) Then Return Self.Gradients[0].Get(y);
59.                 Local i:Double = x * (Self.Gradients.Length-1), i0:Int = Floor(i);
61.         End Method
62.
64.                 If (pId<0 or pId>=Self.Gradients.Length) Then Return Null;
66.         End Method
67. End Type
68.
71.
73.
76.                 Local i:Int; For i=0 Until SizeI; Self.Gradients[i] = Self.NewInstance(SizeJ,SizeK); Next;
77.                 Return Self;
78.         End Method
79.
80.         Method Get:Object(x:Double, y:Double, z:Double)
81.                 If (x<=0) Then Return Self.Gradients[0].Get(y,z);
83.                 Local i:Double = x * (Self.Gradients.Length-1);
84.                 Local i0:Int = Floor(i);
86.         End Method
87.
89.                 If (pId<0 or pId>=Self.Gradients.Length) Then Return Null;
91.         End Method
92.
94.                 If (pIdI<0 or pIdI>=Self.Gradients.Length) Then Return Null;
95.                 If (Self.Gradients[pIdI]=Null) Then Return Null;
97.         End Method
98. End Type
99.
100.
101.
102.
103.
104.
105. ' Prototype for Int4 And Float4 arrays
106. ' for colors or vector position ...
107.
109.         Method NewInstance:Object()
110.                 Return New Int[4];
111.         End Method
112.
115.         End Function
116.
117.         ' Mandatory -> interpolate between two objects and returns an object
118.         Method Interpolate:Object(o1:Object,o2:Object,v:Double)
119.                 Local a:Int[] = Int[](o1)
120.                 Local b:Int[] = Int[](o2)
121.                 ' returns a new array containing a linear interpolated color/position/...
122.                 Return [Int(a[0]+(b[0]-a[0])*v), Int(a[1]+(b[1]-a[1])*v), Int(a[2]+(b[2]-a[2])*v), Int(a[3]+(b[3]-a[3])*v)];
123.         End Method
124.
125.         Method Int4:Int[](x:Double)
126.                 Return Int[] (Self.Get(x));
127.         End Method
128. End type
129.
133.         End Method
134.
137.         End Function
138.
139.         Method Int4:Int[](x:Double,y:Double)
140.                 Return Int[] (Self.Get(x,y));
141.         End Method
142. End Type
143.
147.         End Method
148.
151.         End Function
152.
153.         Method Int4:Int[](x:Double,y:Double,z:Double)
154.                 Return Int[] (Self.Get(x,y,z));
155.         End Method
156. End Type
157.
158.
159.
160.
162.         Method NewInstance:Object()
163.                 Return New Float[4];
164.         End Method
165.
168.         End Function
169.
170.         Method Interpolate:Object(o1:Object,o2:Object,d:Double)
171.                 Local a:Float[] = Float[](o1);
172.                 Local b:Float[] = Float[](o2);
173.                 Local v:Float = d;
174.                 Return [a[0]+(b[0]-a[0])*v, a[1]+(b[1]-a[1])*v, a[2]+(b[2]-a[2])*v, a[3]+(b[3]-a[3])*v];
175.         End Method
176.
177.         Method Float4:Float[](x:Double)
178.                 Return Float[] (Self.Get(x));
179.         End Method
180. End type
181.
185.         End Method
186.
189.         End Function
190.
191.         Method Float4:Float[](x:Double,y:Double)
192.                 Return Float[] (Self.Get(x,y));
193.         End Method
194. End Type
195.
199.         End Method
200.
203.         End Function
204.
205.         Method Float4:Float[](x:Double,y:Double,z:Double)
206.                 Return Float[] (Self.Get(x,y,z));
207.         End Method
208. End Type

_PJ_(Posted 7 months ago)

By use of cosine, you can produce smoother gradients between similar values or at extremeties.Assume scale value of 0 to 1Cos(value*2*Pi)=1 to -1So Smooth= - (Cos(Value * 2 *Pi)+1) * 0.5

Bobysait(Posted 7 months ago)

<div class="quote"> See the extended types for more details (they use linear interpolation, but they can be replaced by cos/sin/square interpolation etc ...) </div>it's up to you to set the interpolate method to use cos interpolation. I used linear because it's faster and only for purpose.For example, in the Float4Gradient Interpolate method, we just replace
Code: [Select]
` Local v:Float = d;`by this( -> result of sin [-Pi/2, +Pi/2] goes from -1 to 1 -> multiply the result by 0.5 to get [-0.5,0.5] range then add 0.5 to get [0.0,1.0]. And simple as that, you have your smooth interpolation )
Code: [Select]
` Local v:Float = 0.5+0.5*Sin(d*180-90); ' sinus interpolation smooth up -> higher medium -> smooth down`