January 15, 2021, 06:01:35 PM

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

Offline 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
-> Extends the types (BGradient, BGradient2, and BGradient3) to use it
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.
  5. Save it as YOUR_BLITZMAX_PATH/mod/MDT.mod/Gradient.bmx
  6. EndRem
  7.  
  8. 'Module MDT.Gradient
  9.  
  10. ' Abstract type ! Don't create instance of BGradient without extending it first !
  11. ' for purpose, see the Int4Gradient and Float4Gradient below
  12. Type BGradient Abstract
  13.        
  14.         Field Objects:Object[];
  15.        
  16.         Method Interpolate:Object(a:Object,b:Object, v:Double) Abstract
  17.        
  18.         Method NewInstance:Object() Abstract
  19.        
  20.         Method OnCreate:BGradient(Size:Long=2)
  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.        
  26.         Method SetArray:BGradient( array:Object[])
  27.                 Self.Objects = array;
  28.                 Return Self;
  29.         End Method
  30.        
  31.         Method Set:BGradient(id:Long, o:Object)
  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.  
  45. Type BGradient2 Abstract
  46.         Field Gradients:BGradient[];
  47.        
  48.         Method NewInstance:BGradient(SizeJ:Long) Abstract
  49.        
  50.         Method OnCreate:BGradient2(SizeI:Long=2, SizeJ:Long=2)
  51.                 Self.Gradients = New BGradient[SizeI];
  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);
  58.                 If (x>=1) Then Return Self.Gradients[Self.Gradients.Length-1].Get(y);
  59.                 Local i:Double = x * (Self.Gradients.Length-1), i0:Int = Floor(i);
  60.                 Return Self.Gradients[0].Interpolate (Self.Gradients[i0].Get(y), Self.Gradients[i0+1].Get(y), i-i0);
  61.         End Method
  62.        
  63.         Method Gradient:BGradient(pId:Long)
  64.                 If (pId<0 or pId>=Self.Gradients.Length) Then Return Null;
  65.                 Return Self.Gradients[pId];
  66.         End Method
  67. End Type
  68.  
  69. Type BGradient3 Abstract
  70.         Field Gradients:BGradient2[];
  71.        
  72.         Method NewInstance:BGradient2(SizeJ:Long, SizeK:Long) Abstract
  73.        
  74.         Method OnCreate:BGradient3(SizeI:Long=2, SizeJ:Long=2, SizeK:Long=2)
  75.                 Self.Gradients = New BGradient2[SizeI];
  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);
  82.                 If (x>=1) Then Return Self.Gradients[Self.Gradients.Length-1].Get(y,z);
  83.                 Local i:Double = x * (Self.Gradients.Length-1);
  84.                 Local i0:Int = Floor(i);
  85.                 Return Self.Gradients[0].Gradients[0].Interpolate (Self.Gradients[i0].Get(y,z), Self.Gradients[i0+1].Get(y,z), i-i0);
  86.         End Method
  87.        
  88.         Method Gradient2:BGradient2(pId:Long)
  89.                 If (pId<0 or pId>=Self.Gradients.Length) Then Return Null;
  90.                 Return Self.Gradients[pId];
  91.         End Method
  92.        
  93.         Method Gradient:BGradient(pIdI:Long, pIdJ:Long)
  94.                 If (pIdI<0 or pIdI>=Self.Gradients.Length) Then Return Null;
  95.                 If (Self.Gradients[pIdI]=Null) Then Return Null;
  96.                 Return Self.Gradients[pIdI].Gradient(pIdJ);
  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.  
  108. Type Int4Gradient Extends BGradient
  109.         Method NewInstance:Object()
  110.                 Return New Int[4];
  111.         End Method
  112.        
  113.         Function Create:Int4Gradient(Size:Long=2)
  114.                 Return Int4Gradient(New Int4Gradient.OnCreate(Size));
  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.  
  130. Type Int4Gradient2 Extends BGradient2
  131.         Method NewInstance:BGradient(SizeJ:Long)
  132.                 Return New Int4Gradient.OnCreate(SizeJ);
  133.         End Method
  134.        
  135.         Function Create:Int4Gradient2(SizeI:Long=2, SizeJ:Long=2)
  136.                 Return Int4Gradient2(New Int4Gradient2.OnCreate(SizeI,SizeJ));
  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.  
  144. Type Int4Gradient3 Extends BGradient3
  145.         Method NewInstance:BGradient2(SizeJ:Long, SizeK:Long)
  146.                 Return New Int4Gradient2.OnCreate(SizeJ, SizeK);
  147.         End Method
  148.        
  149.         Function Create:Int4Gradient3(SizeI:Long=2, SizeJ:Long=2, SizeK:Long=2)
  150.                 Return Int4Gradient3(New Int4Gradient3.OnCreate(SizeI,SizeJ,SizeK));
  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.  
  161. Type Float4Gradient Extends BGradient
  162.         Method NewInstance:Object()
  163.                 Return New Float[4];
  164.         End Method
  165.        
  166.         Function Create:Float4Gradient(Size:Long=2)
  167.                 Return Float4Gradient(New Float4Gradient.OnCreate(Size));
  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.  
  182. Type Float4Gradient2 Extends BGradient2
  183.         Method NewInstance:BGradient(SizeJ:Long)
  184.                 Return New Float4Gradient.OnCreate(SizeJ);
  185.         End Method
  186.        
  187.         Function Create:Float4Gradient2(SizeI:Long=2, SizeJ:Long=2)
  188.                 Return Float4Gradient2(New Float4Gradient2.OnCreate(SizeI,SizeJ));
  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.  
  196. Type Float4Gradient3 Extends BGradient3
  197.         Method NewInstance:BGradient2(SizeJ:Long, SizeK:Long)
  198.                 Return New Float4Gradient2.OnCreate(SizeJ, SizeK);
  199.         End Method
  200.        
  201.         Function Create:Float4Gradient3(SizeI:Long=2, SizeJ:Long=2, SizeK:Long=2)
  202.                 Return Float4Gradient3(New Float4Gradient3.OnCreate(SizeI,SizeJ,SizeK));
  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


Comments :


_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


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal