What kind of math do i need for curves?

Started by
10 comments, last by leiavoia 19 years, 7 months ago
Here is what i want to make. Please tell me what i need to read up on in order to get it working. Please forgive me for not remembering my highschool math so well ;-) I want to build a "color curve". Basically, i want a list of X number of arbitrary RGB colors tied to a point in time. So basically its a simple graph:

C  |              X
O  |  X  
L  |
O  |       X
R  |________________
        TIME 
I want to be able to interpolate values in between the points with a curve.

C  | X            X
O  |  X         XX
L  |   XX     XX
O  |     XXXXX
R  |________________
        TIME 
I know this is simple but i'm not sure of the terminology and whatnot in order to be able to look it up on my own. If you want to explain it to me personally, that would be even better. Please remember that i am looking for an arbitrary number of points, not simply two or three. Thanks
Advertisement
you're looking for something called: "curve fitting". i'm pretty sure it's calculus you'll be needing according to my 10 minute google search.

-me
Perhaps i should also ask: is there a faster way to do this altogether?

What i'm trying to do is make a color ramp for things like particles and effects which need to change colors or fade. So want an object that i can set with a series of colors to flip through

[ percentage of run time, color ]

0.00 - PINK
0.10 - BLUE
0.35 - LIGHTBLUE
0.80 - WHITE
1.00 - YELLOW

for instance. Than i want to say:

color_curve.GetRedAtInterval( 0.6 );

and because of it's rather sloppy nature, i'm not in need of something ultra-precise, just quick and usable.
You can try LaGrangian Interpolation. It's a method in which you give it n points, and it will create a polynomial that passes through those n points. If you're having trouble understanding/implementing it, then ask more.

[edit]
Didnt see that second post of yours. Making a function like color_value.GetRedAt( 0.6 ) shouldnt be that difficult without the above method i mentioned. You can just use linear interpolation between the two colors. Get the difference between the time the color starts and the time the color ends and the see how much the time requested is into that and lerp. Hard to explain, I think code will help:

Color Lerp( Color one, Color two, float time ){  Color out;  out.r = one.r + time * (two.r - one.r);  out.g = one.g + time * (two.g - one.g);  out.b = one.b + time * (two.b - one.b);  out.r = one.a + time * (two.a - one.a);}BYTE color_value::GetRedAt( float time ){  // totalTime is total time from start to finish.  // In your case its 0 to 1 (pink to yellow)  // colors is a std::vector container that has the  // DIfferent color values stored at differen times  // struct ColorTime  // {   //   Color col;  //   float at;  // };  // std::vector<ColorTime> colors;  for( int i = 0; i < colors.size() - 1; ++i )  {    if( colors.at <= time && colors.at &gt;= time )<br>    {<br>      // Found our color. <br>      float difference = colors.at - colors<span style="font-weight:bold;">.at;<br>      float s = difference / ( time - colors<span style="font-weight:bold;">.at );<br>      Color c = Lerp( colors<span style="font-weight:bold;">.color, colors.color, s );<br>      return c.r;<br>    }<br>  }<br>}<br></pre><br><br><!–EDIT–><span class=editedby><!–/EDIT–>[Edited by - IFooBar on September 17, 2004 11:33:44 PM]<!–EDIT–></span><!–/EDIT–>
[size=2]aliak.net
LaGrangian interpolation probably isn't what you want. Unless your points are very well placed, it will be wavy and the interpolated values will go outside the range [0,1].

I recommend using a piecewise cubic curve of some kind. You might try a natural cubic spline or a Catmull-Rom spline. Both are fairly easy to calculate once you understand the math, and both should give excellent results.

-- Eric Lengyel
have you tried just a simple piecewise-linear?

I have to echo Eric Lengyel about polynomial interpolations...they are easy and look great, as long as they don't need to be clipped.

I say start simple.
At first i was going to snub the linear idea, but now that i think about it, that's how a "color ramp" would work anyway, isn't it? Maybe i'm making the whole thing much too over complicated.


Like let's say i have this (letters represent colors in a gradient):

A--------------B---------------------------------C                        ^


At the specified point, the color would be about 25% B and 75% C. That's very easy to figure out.

If i missed something, please let me know. It's not all a waste, i did go explore Lagrange interpolation for an hour or two and almost had a new class debugged for it. I even relearned Sigma and Pi Notation ;-)
Simple linear, cubic or cosine interpolation methods should work just fine. Use cubic for a continuous curve which will pass through all given control points, or cosine for a cruder, slightly faster approximation of a curve passing through all control points. The actual visible differences between the various methods in this context are probably going to be so slight as to likely not be noticeable, so I would tend to favor simple linear interpolation. Note that you probably will want to pre-generate a lookup table if the color ramp is going to be accessed frequently, as a table lookup will be much cheaper than evaluating a curve every time. Since you want to use it for color-changing particles, I'd recommend this approach. Just allocate an array of RGBs, and fill it with evaluated samples when the color ramp is constructed.
Check out this site:

http://astronomy.swin.edu.au/~pbourke/analysis/interpolation/
creating your own interpolation function isnt really as hard as it might seem.

1. what do you know?

color(p1) = c1
color(p2) = c2
color(p3) = c3

2. hmmm, three constraints, means we can solve for three unknown

3. ax^2 + bx + c has three unknown, how handy. so lets say color(x) = ax^2 + bx + c

thus we know:

ap1^2 + bp1 + c = c1
ap2^2 + bp2 + c = c2
ap3^2 + bp3 + c = c3

all p and c is know, lets take a few sample values:
p1 = 0, p2 = 1, p3 = 2
c1 = .9, c2 = .2, c3 = .5

now our formulas simplify to:

c = .9
a + b + c = .2
4a + 2b + c = .5

a + b = -.7
b = -.2 - 2a
a = .5
b = -1.2

color(x) = .5x^2 - 1.2x + .9


the same simple steps can be applied to any dataset you wish to interpolate between using a polynomal.

This topic is closed to new replies.

Advertisement