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

bspline.cpp

Go to the documentation of this file.
00001 #include <windows.h>
00002 #include "shared.h"
00003 #include "bspline.h"
00004 #include "tll.h"
00005 #include "camera.h"
00006 #include "light.h"
00007 #include "mmgr.h"
00008 
00009 extern LIGHT* light;
00010 extern int currentLight;
00011 extern CAMERA* camera;
00012 extern int currentCamera;
00013 extern float ApplicationStartTime;              // Start time required for spline timing
00014 extern int numSplines;
00015 extern int visible;
00016 extern int cameraMode;
00017 extern int currentSpline;
00018 extern int lookAtPath;
00019 extern char SplineFileName[MAX_PATH];
00020 extern SPLINE* spline;
00021 
00022 int SPLINE::Compare(const SPLINE& Spline)
00023 {
00024   if (linkPosition < Spline.linkPosition)
00025     return smaller;
00026   if (linkPosition > Spline.linkPosition)
00027     return bigger;
00028   else
00029     return same;
00030 }
00031 
00032 /*********************************************************************
00033 
00034  Simple b-spline curve algorithm
00035 
00036  Copyright 1994 by Keith Vertanen (vertankd@cda.mrs.umn.edu)
00037  Released to the public domain (your mileage may vary)
00038     Modified by Alan Baylis 2001 (thegoodalien@inorbit.com)
00039 
00040 **********************************************************************/
00041 
00042 // puts the number of points specified by NumPoints in the spline's Output array
00043 void bspline(SPLINE* spline)
00044 {
00045     int t = spline->Degree;
00046     int n = spline->NumControl;
00047     int num_output = spline->NumPoints;
00048     VECTOR* control = spline->Control;
00049 
00050     int* u;
00051 
00052     int output_index;
00053     float increment,interval;
00054     VECTOR calcxyz;
00055 
00056     u = new int[n+t+1];
00057     compute_intervals(u, n, t);
00058 
00059     increment = (float) (n-t+2) / (num_output-1);  // how much parameter goes up each time
00060     interval = 0;
00061 
00062     for (output_index = 0; output_index < num_output - 1; output_index++)
00063     {
00064         compute_point(u, n, t, interval, control, &calcxyz);
00065         spline->Output[output_index].x = calcxyz.x;
00066         spline->Output[output_index].y = calcxyz.y;
00067         spline->Output[output_index].z = calcxyz.z;
00068         interval = interval + increment;  // increment our parameter
00069     }
00070     spline->Output[num_output-1].x = control[n].x;   // put in the last point
00071     spline->Output[num_output-1].y = control[n].y;
00072     spline->Output[num_output-1].z = control[n].z;
00073 
00074     delete u;
00075 }
00076 
00077 // returns a single point based on the spline start and end times
00078 VECTOR bsplinepoint(SPLINE* spline)
00079 {
00080     int t = spline->Degree;
00081     int n = spline->NumControl;
00082     VECTOR *control = spline->Control;
00083 //    VECTOR *output = spline->Output;
00084 
00085     int* u;
00086     float increment;
00087     VECTOR calcxyz;
00088 
00089     u = new int[n+t+1];
00090     compute_intervals(u, n, t);
00091 
00092     float CurrentTime = (float)GetTickCount() - ApplicationStartTime;
00093 
00094     float TotalTime = spline->EndTime - spline->StartTime;
00095     float Position;
00096     float ActualTime;
00097 
00098     if (CurrentTime <= spline->CopyOfStartTime)
00099     {
00100         calcxyz.x = control[0].x;
00101         calcxyz.y = control[0].y;
00102         calcxyz.z = control[0].z;
00103         delete u;
00104         return calcxyz;
00105     }
00106     else if (CurrentTime >= spline->CopyOfEndTime)
00107     {
00108         if (spline->Repeat)
00109         {
00110             spline->CopyOfStartTime = CurrentTime;
00111             spline->CopyOfEndTime = CurrentTime + TotalTime;
00112         }
00113         calcxyz.x = control[n].x;
00114         calcxyz.y = control[n].y;
00115         calcxyz.z = control[n].z;
00116         delete u;
00117         return calcxyz;
00118     }
00119     else
00120     {
00121         ActualTime = CurrentTime - spline->CopyOfStartTime;
00122         Position = 1 / (TotalTime / ActualTime);
00123     }
00124     increment = (n - t + 2) * Position;  // how much parameter goes up each time
00125 
00126     compute_point(u, n, t, increment, control, &calcxyz);
00127 
00128     delete u;
00129 
00130     return calcxyz;
00131 }
00132 
00133 float blend(int k, int t, int *u, float v)  // calculate the blending value
00134 {
00135     float value;
00136 
00137     if (t == 1)            // base case for the recursion
00138     {
00139         if ((u[k] <= v) && (v < u[k+1]))
00140             value = 1;
00141         else
00142             value = 0;
00143     }
00144     else
00145     {
00146         if ((u[k+t-1] == u[k]) && (u[k+t] == u[k+1]))         // check for divide by zero
00147             value = 0;
00148         else
00149             if (u[k+t-1] == u[k])           // if a term's denominator is zero,use just the other
00150                 value = (u[k+t] - v) / (u[k+t] - u[k+1]) * blend(k+1, t-1, u, v);
00151             else
00152                 if (u[k+t]==u[k+1])
00153                     value = (v - u[k]) / (u[k+t-1] - u[k]) * blend(k, t-1, u, v);
00154                 else
00155                     value = (v - u[k]) / (u[k+t-1] - u[k]) * blend(k, t-1, u, v) + (u[k+t] - v) / (u[k+t] - u[k+1]) * blend(k+1, t-1, u, v);
00156     }
00157     return value;
00158 }
00159 
00160 void compute_intervals(int *u, int n, int t)   // figure out the knots
00161 {
00162     int j;
00163 
00164     for (j = 0; j <= n+t; j++)
00165     {
00166         if (j<t)
00167             u[j]=0;
00168         else
00169             if ((t <= j) && (j <= n))
00170                 u[j] = j-t+1;
00171             else
00172                 if (j > n)
00173                     u[j] = n-t+2;  // if n-t=-2 then we're screwed, everything goes to 0
00174     }
00175 }
00176 
00177 void compute_point(int *u, int n, int t, float v, VECTOR *control, VECTOR *output)
00178 {
00179     int k;
00180     float temp;
00181 
00182     // initialize the variables that will hold our outputted point
00183     output->x=0;
00184     output->y=0;
00185     output->z=0;
00186 
00187     for (k = 0; k <= n; k++)
00188     {
00189         temp = blend(k,t,u,v);  // same blend is used for each dimension coordinate
00190         output->x = output->x + (control[k]).x * temp;
00191         output->y = output->y + (control[k]).y * temp;
00192         output->z = output->z + (control[k]).z * temp;
00193     }
00194 }
00195 
00196 void DrawSplines(LinkedList<SPLINE>& SplineList)
00197 {
00198     GLUquadricObj * sphere = gluNewQuadric();      // sphere for control points
00199 
00200     for (int loop = 0; loop < numSplines; loop++)     // loop through all splines
00201     {
00202         spline = SplineList.Get(loop);               // get the spline from the linked list
00203 
00204         if (visible)                                 // if the curves are visible
00205         {
00206             // draw the control points
00207             glDisable(GL_TEXTURE_2D);
00208             float mat_ambient[] = {spline->Red, spline->Green, spline->Blue, 1.0 };
00209             float mat_diffuse[] = {spline->Red, spline->Green, spline->Blue, 1.0 };
00210             float mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
00211             glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
00212             glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
00213             glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
00214             for (int i=0; i <= spline->NumControl; i++)
00215             {
00216                 glPushMatrix();
00217                 glTranslatef(spline->Control[i].x, spline->Control[i].y, spline->Control[i].z);
00218                 gluSphere(sphere,0.4,10,10);
00219                 glPopMatrix();
00220             }
00221             glEnable(GL_TEXTURE_2D);
00222 
00223             // get the output point of this spline
00224             VECTOR Output = bsplinepoint(spline);
00225 
00226             // draw the point
00227             glPointSize(5.0);
00228             glColor3f(0.0, 1.0 ,0.0);
00229             glDisable(GL_TEXTURE_2D);
00230             glDisable(GL_LIGHTING);
00231             glPushMatrix();
00232             glBegin(GL_POINTS);
00233             glVertex3f(Output.x, Output.y, Output.z);
00234             glEnd();
00235             glPopMatrix();
00236             glEnable(GL_TEXTURE_2D);
00237             glEnable(GL_LIGHTING);
00238 
00239             if (cameraMode > 0 && currentSpline == loop) // if the camera mode is not free and this is the current spline
00240             {
00241                 VECTOR LookAt;
00242                 if (cameraMode == 2 && (currentSpline != lookAtPath)) // if the camera mode is follow
00243                 {
00244                     SPLINE* spline2 = SplineList.Get(lookAtPath);
00245                     LookAt = bsplinepoint(spline2);
00246                 }
00247                 camera[currentCamera].Position.x = Output.x;  // set the camera position to the current spline output
00248                 camera[currentCamera].Position.y = Output.y;
00249                 camera[currentCamera].Position.z = Output.z;
00250                 MATRIX mat;
00251                 glPushMatrix();
00252                 glLoadIdentity();
00253                 if (cameraMode == 2 && (currentSpline != lookAtPath)) // if the camera mode is follow
00254                     gluLookAt(Output.x, Output.y, Output.z, LookAt.x, LookAt.y, LookAt.z, 0, 1, 0);
00255                 else
00256                                                                       // else make the camera look at another position
00257                     gluLookAt(Output.x, Output.y, Output.z, light[currentLight].Position.x, light[currentLight].Position.y, light[currentLight].Position.z, 0, 1, 0);
00258                 glGetFloatv(GL_MODELVIEW_MATRIX, mat.Element);       // get the gluLookAt matrix
00259                 glPopMatrix();
00260 
00261                 float mat2[4][4];
00262                 mat2[0][0] = mat.Element[0];
00263                 mat2[0][1] = mat.Element[1];
00264                 mat2[0][2] = mat.Element[2];
00265                 mat2[0][3] = mat.Element[3];
00266                 mat2[1][0] = mat.Element[4];
00267                 mat2[1][1] = mat.Element[5];
00268                 mat2[1][2] = mat.Element[6];
00269                 mat2[1][3] = mat.Element[7];
00270                 mat2[2][0] = mat.Element[8];
00271                 mat2[2][1] = mat.Element[9];
00272                 mat2[2][2] = mat.Element[10];
00273                 mat2[2][3] = mat.Element[11];
00274                 mat2[3][0] = mat.Element[12];
00275                 mat2[3][1] = mat.Element[13];
00276                 mat2[3][2] = mat.Element[14];
00277                 mat2[3][3] = mat.Element[15];
00278 
00279                 camera[currentCamera].Orientation.MatrixToQuat(mat2);  // set the camera orientation to the gluLookAt matrix
00280             }
00281 
00282             bspline(spline);             // get the output points of this spline
00283 
00284             // draw the curve along to the output points
00285             glColor3f(spline->Red, spline->Green, spline->Blue);
00286             glDisable(GL_TEXTURE_2D);
00287             glDisable(GL_LIGHTING);
00288             glPushMatrix();
00289             glBegin(GL_LINE_STRIP);
00290             for (int i=0; i < spline->NumPoints; i++)
00291             {
00292                 glVertex3fv(&spline->Output[i].x);
00293             }
00294             glEnd();
00295             glPopMatrix();
00296             glEnable(GL_TEXTURE_2D);
00297             glEnable(GL_LIGHTING);
00298         }
00299 
00300         else if (cameraMode > 0) // if the curves are not visible and the camera mode is not free
00301         {
00302             VECTOR Output = bsplinepoint(spline);
00303 
00304             VECTOR LookAt;
00305             if (cameraMode == 2 && currentSpline != lookAtPath)
00306             {
00307                 SPLINE* spline2 = SplineList.Get(lookAtPath);
00308                 LookAt = bsplinepoint(spline2);
00309             }
00310             camera[currentCamera].Position.x = Output.x;
00311             camera[currentCamera].Position.y = Output.y;
00312             camera[currentCamera].Position.z = Output.z;
00313             MATRIX mat;
00314             glPushMatrix();
00315             glLoadIdentity();
00316             if (cameraMode == 2 && currentSpline != lookAtPath)
00317                 gluLookAt(Output.x, Output.y, Output.z, LookAt.x, LookAt.y, LookAt.z, 0, 1, 0);
00318             else
00319                 gluLookAt(Output.x, Output.y, Output.z, light[currentLight].Position.x, light[currentLight].Position.y, light[currentLight].Position.z, 0, 1, 0);
00320             glGetFloatv(GL_MODELVIEW_MATRIX, mat.Element);
00321             glPopMatrix();
00322 
00323             float mat2[4][4];
00324             mat2[0][0] = mat.Element[0];
00325             mat2[0][1] = mat.Element[1];
00326             mat2[0][2] = mat.Element[2];
00327             mat2[0][3] = mat.Element[3];
00328             mat2[1][0] = mat.Element[4];
00329             mat2[1][1] = mat.Element[5];
00330             mat2[1][2] = mat.Element[6];
00331             mat2[1][3] = mat.Element[7];
00332             mat2[2][0] = mat.Element[8];
00333             mat2[2][1] = mat.Element[9];
00334             mat2[2][2] = mat.Element[10];
00335             mat2[2][3] = mat.Element[11];
00336             mat2[3][0] = mat.Element[12];
00337             mat2[3][1] = mat.Element[13];
00338             mat2[3][2] = mat.Element[14];
00339             mat2[3][3] = mat.Element[15];
00340 
00341             camera[currentCamera].Orientation.MatrixToQuat(mat2);
00342         }
00343     }
00344 }

Generated on Fri Dec 23 05:20:17 2005 for Portals by doxygen1.2.15