Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

bezier.cpp

Go to the documentation of this file.
00001 /*
00002         ------------------------------------------------------------------------
00003         ClanLib, the platform independent game SDK.
00004 
00005         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00006         version 2. See COPYING for details.
00007 
00008         For a total list of contributers see CREDITS.
00009 
00010         ------------------------------------------------------------------------
00011 */
00012 
00013 #include "Core/precomp.h"
00014 #include "API/Core/Math/bezier.h"
00015 
00016 /*
00017     control points = p1,p2,p3,p4 whereof p1,p4 are endpoints and
00018     p1p2,p3p4 are the respective tangent vectors. If more than one 
00019     curve is concatenated make sure that p4 - p3 = p5 - p4 if you
00020     want C0 and C1 steadyness (sp?)
00021     
00022     for the math freaks: the path is given by
00023     w(t)  = (1-t)^3 * P1 + 3*t*(1-t)^2 * P2 + 3*t^2*(1-t)*P3 + t^3*P4; t in [0,1]
00024     
00025     and the length is 
00026     Lw = /int_{0}^{1} |w'(t)| dt
00027 */
00028 
00029 
00030 CL_BezierCurve::CL_BezierCurve(const CL_Vector *cp, int cs, int steps, bool stepping)
00031 {
00032         curve = new CL_Vector[cs*steps];
00033         this->cp = new CL_Vector[cs*4];
00034         this->steps = steps;
00035         this->stepping = stepping;
00036         this->cs = cs;
00037         
00038         for (int i=0;i<cs*4;i++)
00039                 this->cp[i] = cp[i];
00040 
00041         make_curve();
00042 }
00043 
00044 
00045 CL_BezierCurve::~CL_BezierCurve()
00046 {
00047         delete [] curve;
00048         delete [] cp;
00049 }
00050 
00051 
00052 // hey it is not the fastest code, but I'll change it to a faster algorithm
00053 // somewhen in the future, though this is not a promise ;-) 
00054 // [ actually it is a lie :-) ]
00055 
00056 void CL_BezierCurve::make_curve()
00057 {
00058         // TODO: interpret stepping
00059         for (int n=0; n<cs; n++)
00060         {
00061                 curve[n*steps] = cp[n*4];
00062 
00063                 float t, delta;
00064                 delta = 1.0/steps;
00065         
00066                 for (int i=1; i<steps; i++)
00067                 {
00068                         t = i*delta;
00069                         curve[n*steps+i].x = 
00070                                 cp[n*4+0].x * (1.0 - t) * (1.0 - t) * (1.0 - t) +
00071                                 cp[n*4+1].x * 3.0 * t * (1.0 - t) * (1.0 - t) +
00072                                 cp[n*4+2].x * 3.0 * t *  t  * (1.0 - t) + 
00073                                 cp[n*4+3].x * t * t * t;
00074 
00075                         curve[n*steps+i].y = 
00076                                 cp[n*4+0].y * (1.0 - t) * (1.0 - t) * (1.0 - t) +
00077                                 cp[n*4+1].y * 3.0 * t * (1.0 - t) * (1.0 - t) +
00078                                 cp[n*4+2].y * 3.0 * t *  t  * (1.0 - t) + 
00079                                 cp[n*4+3].y * t * t * t;
00080 
00081                         curve[n*steps+i].z =
00082                                 cp[n*4+0].z * (1.0 - t) * (1.0 - t) * (1.0 - t) +
00083                                 cp[n*4+1].z * 3.0 * t * (1.0 - t) * (1.0 - t) +
00084                                 cp[n*4+2].z * 3.0 * t *  t  * (1.0 - t) + 
00085                                 cp[n*4+3].z * t * t * t;
00086                 }
00087         }
00088 }
00089 
00090 
00091 float CL_BezierCurve::get_length(int segment) const
00092 {
00093         if (segment == -1)
00094         {
00095                 float length = 0;
00096                 for (int i=0;i<cs;i++)
00097                         length += get_length(cs);
00098                 return length;
00099         }
00100         // TODO: calculate Lw for segment
00101         return 0;       
00102 }
00103 
00104 
00105 void CL_BezierCurve::set_steps(int steps)
00106 {
00107         delete [] curve;
00108         curve = new CL_Vector[cs*steps];
00109         this->steps = steps;
00110         make_curve();
00111 }
00112 
00113 
00114 void CL_BezierCurve::set_stepping(bool stepping)
00115 {
00116         this->stepping = stepping;
00117         make_curve();
00118 }
00119 
00120 
00121 // CL_BezierSurface
00122 
00123 CL_BezierSurface::CL_BezierSurface(const CL_Vector *cp, int xs, int ys, int xsteps, int ysteps, bool stepping)
00124 {
00125         surface = new CL_Vector[xs*xsteps*ys*ysteps];
00126         this->cp = new CL_Vector[xs*ys*16];
00127         this->xsteps = xsteps;
00128         this->ysteps = ysteps;
00129         this->stepping = stepping;
00130         this->xs = xs;
00131         this->ys = ys;
00132         
00133         for (int i=0;i<xs*ys*16;i++)
00134                 this->cp[i] = cp[i];
00135 
00136         make_surface();
00137 }
00138 
00139 
00140 CL_BezierSurface::~CL_BezierSurface()
00141 {
00142         delete [] surface;
00143         delete [] cp;
00144 }
00145 
00146 
00147 CL_Vector CL_BezierSurface::evaluate(float s, float t, int offset)
00148 {
00149         int stride = 4 * xs;
00150         CL_Vector v;
00151 
00152         for (int i=0; i<3; i++)
00153         {
00154                 v[i] = (1-s)*(1-s)*(1-s)* (
00155                         cp[offset+0+0*stride][i] * (1-t)*(1-t)*(1-t) + 
00156                         cp[offset+0+1*stride][i] * 3*(1-t)*(1-t)*t + 
00157                         cp[offset+0+2*stride][i] * 3*(1-t)*t*t + 
00158                         cp[offset+0+3*stride][i] *t*t*t) +
00159  
00160                         3*(1-s)*(1-s)*s* (
00161                         cp[offset+1+0*stride][i] * (1-t)*(1-t)*(1-t) + 
00162                         cp[offset+1+1*stride][i] * 3*(1-t)*(1-t)*t + 
00163                         cp[offset+1+2*stride][i] * 3*(1-t)*t*t + 
00164                         cp[offset+1+3*stride][i] *t*t*t) +
00165 
00166                         3*(1-s)*s*s* (
00167                         cp[offset+2+0*stride][i] * (1-t)*(1-t)*(1-t) + 
00168                         cp[offset+2+1*stride][i] * 3*(1-t)*(1-t)*t + 
00169                         cp[offset+2+2*stride][i] * 3*(1-t)*t*t + 
00170                         cp[offset+2+3*stride][i] *t*t*t) +
00171 
00172                         s*s*s* (
00173                         cp[offset+3+0*stride][i] * (1-t)*(1-t)*(1-t) + 
00174                         cp[offset+3+1*stride][i] * 3*(1-t)*(1-t)*t + 
00175                         cp[offset+3+2*stride][i] * 3*(1-t)*t*t + 
00176                         cp[offset+3+3*stride][i] *t*t*t);
00177         }
00178         return v;
00179 } 
00180 
00181 void CL_BezierSurface::make_surface()
00182 {
00183         // TODO: interpret stepping
00184 
00185         for (int y=0; y<ys; y++)
00186         {
00187                 for (int x=0; x<xs; x++)
00188                 {
00189                         float s,t, deltax, deltay;
00190 
00191                         deltax = 1.0/xsteps;
00192                         deltay = 1.0/ysteps;
00193 
00194                         for (int ny=0; ny<ysteps; ny++)
00195                         {
00196                                 for (int nx=0; nx<xsteps; nx++)
00197                                 {
00198                                         s = nx * deltax;
00199                                         t = ny * deltay;
00200                                         
00201                                         surface[y*ysteps*xsteps*xs + x] = evaluate(s,t, y*16*xs + x);
00202                                 }
00203                         }
00204                 }
00205         }
00206 }
00207 
00208 
00209 void CL_BezierSurface::set_xsteps(int xsteps)
00210 {
00211         delete [] surface;
00212         surface = new CL_Vector[xs*xsteps*ys*ysteps];
00213         this->xsteps = xsteps;
00214         make_surface();
00215 }
00216 
00217 
00218 void CL_BezierSurface::set_ysteps(int ysteps)
00219 {
00220         delete [] surface;
00221         surface = new CL_Vector[xs*xsteps*ys*ysteps];
00222         this->ysteps = ysteps;
00223         make_surface();
00224 }
00225 
00226 
00227 void CL_BezierSurface::set_stepping(bool stepping)
00228 {
00229         this->stepping = stepping;
00230         make_surface();
00231 }

Generated at Wed Apr 4 19:53:58 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001