home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 February
/
Chip_2001-02_cd1.bin
/
bonus
/
demos
/
CS
/
exp
/
SOURCES
/
DEMO
/
vlacik2.h
< prev
next >
Wrap
C/C++ Source or Header
|
2000-08-11
|
24KB
|
824 lines
#ifndef _vlacik2_H
#define _vlacik2_H
#define unit_length 100.0
#define straight_line_max (unit_length/5.0)
#define rail_spacing 10.0
#define rail_size 1.4
#define tube_sides 9
#define tube_radius (rail_spacing/2.0+12.0)
#define rail_tube_spacing 6.0
// Sorts of tracks
#define STRAIGHT 1
#define HALFTURN_RIGHT 2
#define QUARTERTURN_RIGHT 3
#define UTURN_RIGHT 4
#define HALFTURN_LEFT 5
#define QUARTERTURN_LEFT 6
#define UTURN_LEFT 7
#define HALFTURN_UP 8
#define QUARTERTURN_UP 9
#define UTURN_UP 10
#define HALFTURN_DOWN 11
#define QUARTERTURN_DOWN 12
#define UTURN_DOWN 13
#define ASCEND 14
#define DESCEND 15
#define ASCEND_LOW 16
#define DESCEND_LOW 17
#define ASCEND_HIGH 18
#define DESCEND_HIGH 19
#define FULLWHIRL 20
#define FULLWHIRL_CLOCKWISE 21
#define HALFWHIRL 22
#define HALFWHIRL_CLOCKWISE 23
#define DOUBLEWHIRL 24
#define DOUBLEWHIRL_CLOCKWISE 25
#define LOOPING 26
// Construction style flags
#define HAS_TUBE 1
struct track_base
{
static Material3DS* rail_material;
static Material3DS* tube_material;
unsigned long flag;
GLmatrix_double cs;
quaternion<double> qcs;
track_base() {
cs.Identity();
qcs = quaternion<double> (1.0, 0.0, 0.0, 0.0);
flag = 0;
}
void CS(const GLmatrix_double& m) {
cs=m;
};
void QCS(const quaternion<double>& q) {
qcs = q;
};
virtual double length() = 0;
virtual Vector3d position(double t) = 0;
virtual Vector3d direction(double t) = 0;
virtual Vector3d udirection(double t) = 0;
virtual double roll(double t) = 0;
virtual quaternion<double> local_orientation(double t) = 0;
virtual RenderableEntityA* rails() = 0;
void normalize(Vector3d &u) {
double l = 1.0/sqrt(u.x*u.x + u.y*u.y + u.z+u.z);
u.x*=l; u.y*=l; u.z*=l;
}
GLmatrix_double answer_cs(const Vector3d &p, const Vector3d &d, const Vector3d &ud, double r) {
Vector3d n, u, v, a,b;
n=d;
u=ud;
v.x=-(u.y*n.z-u.z*n.y);
v.y=-(u.z*n.x-u.x*n.z);
v.z=-(u.x*n.y-u.y*n.x);
double s = sin(r);
double c = cos(r);
a = c*u + s*v;
b = -s*u + c*v;
GLmatrix_double m;
m[0]=a.x; m[4]=b.x; m[8]= n.x; m[12]=p.x;
m[1]=a.y; m[5]=b.y; m[9]= n.y; m[13]=p.y;
m[2]=a.z; m[6]=b.z; m[10]=n.z; m[14]=p.z;
m[3]=0.0; m[7]=0.0; m[11]=0.0; m[15]=1.0;
return m;
}
virtual GLmatrix_double coordinate_system(double t) {
return cs*answer_cs(position(t), direction(t), udirection(t), roll(t));
}
virtual quaternion<double> orientation(double t) {
return qcs*local_orientation(t);
}
virtual RenderableEntityA* tube() {
if(!(flag&HAS_TUBE))
return 0;
GLmatrix_double m;
double d = rail_spacing/2.0;
int parts = (int)(length()/straight_line_max)+1;
Vector3d P, X, Y, V, H, N;
Vertex3DS* v = new Vertex3DS[tube_sides*(parts+1)];
GLuint i = 0;
for(int q=0; q<=parts; q++) {
m = coordinate_system((double)q/(double)parts);
P.x = m[12]; P.y = m[13]; P.z = m[14];
X.x = m[0]; X.y = m[1]; X.z = m[2];
Y.x = m[4]; Y.y = m[5]; Y.z = m[6];
H = Y*sqrt(tube_radius*tube_radius - (d+rail_tube_spacing)*(d+rail_tube_spacing));
for(int k=0; k<tube_sides; k++) {
double a = ((2*PI)/(double)tube_sides)*k;
N = X*cos(a) + Y*sin(a);
V = P + H + tube_radius*N;
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = N.x; v[i].j = N.y; v[i].k = N.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
}
}
RenderableEntityA* obj = new RenderableEntityA;
obj->SetMaterial(tube_material);
obj->Vertices(tube_sides*(parts+1), v);
int isize = (parts+1)<<1;
GLuint* ind[tube_sides];
for(int k=0; k<tube_sides; k++)
ind[k] = new GLuint[isize];
i = 0; int j = 0;
for(int q=0; q<=parts; q++, i+=tube_sides, j+=2) {
for(int k=0; k<tube_sides; k++) {
*(ind[k]+j) = i+k;
*(ind[k]+j+1) = i+((k+1)%tube_sides);
}
}
for(int k=0; k<tube_sides; k++)
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind[k]);
return obj;
}
};
// initialization of static data
Material3DS* track_base::rail_material = 0;
Material3DS* track_base::tube_material = 0;
// STRAIGHT
struct straight_track : public track_base
{
double len;
void Length(double f) { len=f; }
virtual double length() { return len; }
virtual Vector3d position(double t) {
return Vector3d(0.0, 0.0, t*len);
}
virtual Vector3d direction(double t) {
return Vector3d(0.0, 0.0, 1.0);
}
virtual Vector3d udirection(double t) {
return Vector3d(1.0, 0.0, 0.0);
}
virtual double roll(double t) {
return 0;
}
virtual quaternion<double> local_orientation(double t) {
return quaternion<double> (1.0, 0.0, 0.0, 0.0);
}
virtual RenderableEntityA* rails() {
GLmatrix_double m;
double d = rail_spacing/2.0;
int parts = 1;
Vector3d P, X, Y, V;
Vertex3DS* v = new Vertex3DS[6*(parts+1)];
GLuint i = 0;
for(int q=0; q<=parts; q++) {
m = coordinate_system((double)q/(double)parts);
P.x = m[12]; P.y = m[13]; P.z = m[14];
X.x = m[0]; X.y = m[1]; X.z = m[2];
Y.x = m[4]; Y.y = m[5]; Y.z = m[6];
V = P - X*(d + rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = -X.x; v[i].j = -X.y; v[i].k = -X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P - X*(d - rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = X.x; v[i].j = X.y; v[i].k = X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P - X*d + Y*rail_size;
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = Y.x; v[i].j = Y.y; v[i].k = Y.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P + X*(d - rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = -X.x; v[i].j = -X.y; v[i].k = -X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P + X*(d + rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = X.x; v[i].j = X.y; v[i].k = X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P + X*d + Y*rail_size;
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = Y.x; v[i].j = Y.y; v[i].k = Y.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
}
RenderableEntityA* obj = new RenderableEntityA;
obj->SetMaterial(rail_material);
obj->Vertices(6*(parts+1), v);
int isize = (parts+1)<<1;
GLuint* ind1 = new GLuint[isize];
GLuint* ind2 = new GLuint[isize];
GLuint* ind3 = new GLuint[isize];
GLuint* ind4 = new GLuint[isize];
GLuint* ind5 = new GLuint[isize];
GLuint* ind6 = new GLuint[isize];
i = 0; int j = 0;
for(int q=0; q<=parts; q++, i+=6, j+=2) {
ind1[j] = i;
ind1[j+1] = i+1;
ind2[j] = i+1;
ind2[j+1] = i+2;
ind3[j] = i+2;
ind3[j+1] = i;
ind4[j] = i+3;
ind4[j+1] = i+4;
ind5[j] = i+4;
ind5[j+1] = i+5;
ind6[j] = i+5;
ind6[j+1] = i+3;
}
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind1);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind2);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind3);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind4);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind5);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind6);
return obj;
}
};
// curved base
struct track_base_curved : public track_base
{
virtual RenderableEntityA* rails() {
GLmatrix_double m;
double d = rail_spacing/2.0;
int parts = (int)(length()/straight_line_max)+1;
Vector3d P, X, Y, V;
Vertex3DS* v = new Vertex3DS[6*(parts+1)];
GLuint i = 0;
for(int q=0; q<=parts; q++) {
m = coordinate_system((double)q/(double)parts);
P.x = m[12]; P.y = m[13]; P.z = m[14];
X.x = m[0]; X.y = m[1]; X.z = m[2];
Y.x = m[4]; Y.y = m[5]; Y.z = m[6];
V = P - X*(d + rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = -X.x; v[i].j = -X.y; v[i].k = -X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P - X*(d - rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = X.x; v[i].j = X.y; v[i].k = X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P - X*d + Y*rail_size;
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = Y.x; v[i].j = Y.y; v[i].k = Y.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P + X*(d - rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = -X.x; v[i].j = -X.y; v[i].k = -X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P + X*(d + rail_size*0.5);
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = X.x; v[i].j = X.y; v[i].k = X.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
V = P + X*d + Y*rail_size;
v[i].x = V.x; v[i].y = V.y; v[i].z = V.z; v[i].w = 1.0F;
v[i].i = Y.x; v[i].j = Y.y; v[i].k = Y.z;
v[i].R = v[i].G = v[i].B = v[i].A = 1.0F;
v[i].s = v[i].t = v[i].r = 0.0F; v[i].q = 1.0F;
i++;
}
RenderableEntityA* obj = new RenderableEntityA;
obj->SetMaterial(rail_material);
obj->Vertices(6*(parts+1), v);
int isize = (parts+1)<<1;
GLuint* ind1 = new GLuint[isize];
GLuint* ind2 = new GLuint[isize];
GLuint* ind3 = new GLuint[isize];
GLuint* ind4 = new GLuint[isize];
GLuint* ind5 = new GLuint[isize];
GLuint* ind6 = new GLuint[isize];
i = 0; int j = 0;
for(int q=0; q<=parts; q++, i+=6, j+=2) {
ind1[j] = i;
ind1[j+1] = i+1;
ind2[j] = i+1;
ind2[j+1] = i+2;
ind3[j] = i+2;
ind3[j+1] = i;
ind4[j] = i+3;
ind4[j+1] = i+4;
ind5[j] = i+4;
ind5[j+1] = i+5;
ind6[j] = i+5;
ind6[j+1] = i+3;
}
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind1);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind2);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind3);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind4);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind5);
obj->AddElement(GL_TRIANGLE_STRIP, isize, ind6);
return obj;
}
};
// circular base
struct circular_track : public track_base_curved
{
double a, b;
double radius;
double clk;
circular_track() : a(0), b(0), radius(0), clk(1) {}
void A(double f) { a=f; }
void B(double f) { b=f; }
void Radius(double f) { radius=f; }
void Clk(double f) { clk=f; }
virtual double length() { return radius*fabs(a-b); }
};
// HORIZONTAL
struct turn_track_horizontal : public circular_track
{
virtual Vector3d position(double t) {
double tt = a + t*(b-a);
return Vector3d(radius*(cos(tt)-cos(a)),
0.0,
radius*(sin(tt)-sin(a)));
}
virtual Vector3d direction(double t) {
double tt = a + t*(b-a);
return Vector3d(-sin(tt)*clk, 0.0, cos(tt)*clk);
}
virtual Vector3d udirection(double t) {
double tt = a + t*(b-a);
return Vector3d(cos(tt)*clk, 0.0, sin(tt)*clk);
}
virtual quaternion<double> local_orientation(double t) {
return AngleAxis2Quaternion(-t*(b-a), 0.0, 1.0, 0.0);
}
virtual double roll(double t) {
return 0;
}
};
struct halfturn_left : public turn_track_horizontal {
halfturn_left() { a=PI; b=PI/2.0; clk=-1.0; }
};
struct quarterturn_left : public turn_track_horizontal {
quarterturn_left() { a=PI; b=(3*PI)/4.0; clk=-1.0; }
};
struct uturn_left : public turn_track_horizontal {
uturn_left() { a=PI; b=0.0; clk=-1.0; }
};
struct halfturn_right : public turn_track_horizontal {
halfturn_right() { a=0.0; b=PI/2.0; clk=1.0; }
};
struct quarterturn_right : public turn_track_horizontal {
quarterturn_right() { a=0.0; b=PI/4.0; clk=1.0; }
};
struct uturn_right : public turn_track_horizontal {
uturn_right() { a=0.0; b=PI; clk=1.0; }
};
// VERTICAL
struct turn_track_vertical : public circular_track
{
virtual Vector3d position(double t) {
double tt = a + t*(b-a);
return Vector3d(0.0,
radius*(sin(tt)-sin(a)),
radius*(cos(tt)-cos(a)));
}
virtual Vector3d direction(double t) {
double tt = a + t*(b-a);
return Vector3d(0.0, cos(tt)*clk, -sin(tt)*clk);
}
virtual Vector3d udirection(double t) {
double tt = a + t*(b-a);
return Vector3d(1.0, 0.0, 0.0);
}
virtual double roll(double t) {
return 0;
}
virtual quaternion<double> local_orientation(double t) {
return AngleAxis2Quaternion(-t*(b-a), 1.0, 0.0, 0.0);
}
};
struct ascend : public turn_track_vertical {
ascend() { a=(3*PI)/2.0; b=(7*PI)/4.0; clk=1.0; }
};
struct descend : public turn_track_vertical {
descend() { a=PI/2.0; b=PI/4.0; clk=-1.0; }
};
struct ascend_low : public turn_track_vertical {
ascend_low() { a=(3*PI)/2.0; b=(5*PI)/3.0; clk=1.0; }
};
struct descend_low : public turn_track_vertical {
descend_low() { a=PI/2.0; b=PI/3.0; clk=-1.0; }
};
struct ascend_high : public turn_track_vertical {
ascend_high() { a=(3*PI)/2.0; b=(11*PI)/6.0; clk=1.0; }
};
struct descend_high : public turn_track_vertical {
descend_high() { a=PI/2.0; b=PI/6.0; clk=-1.0; }
};
struct halfturn_down : public turn_track_vertical {
halfturn_down() { a=PI/2.0; b=0.0; clk=-1.0; }
};
struct quarterturn_down : public turn_track_vertical {
quarterturn_down() { a=PI/2.0; b=PI/4.0; clk=-1.0; }
};
struct uturn_down : public turn_track_vertical {
uturn_down() { a=PI/2.0; b=-PI/2.0; clk=-1.0; }
};
struct halfturn_up : public turn_track_vertical {
halfturn_up() { a=(3*PI)/2.0; b=2*PI; clk=1.0; }
};
struct quarterturn_up : public turn_track_vertical {
quarterturn_up() { a=(3*PI)/2.0; b=(7*PI)/4.0; clk=1.0; }
};
struct uturn_up : public turn_track_vertical {
uturn_up() { a=(3*PI)/2.0; b=(5*PI)/2; clk=1.0; }
};
// LOOPINGS
struct loopings : public circular_track
{
virtual Vector3d position(double t) {
Vector3d v;
double tt = a + t*(b-a);
v.x = (rail_spacing)*sin(t*PI/2.0)*sin(t*PI/2.0);
v.y = radius*(sin(tt)-sin(a));
v.z = radius*(cos(tt)-cos(a));
return v;
}
virtual Vector3d direction(double t) {
double tt = a + t*(b-a);
return Vector3d(0.0, cos(tt)*clk, -sin(tt)*clk);
}
virtual Vector3d udirection(double t) {
return Vector3d(1.0, 0.0, 0.0);
}
virtual double roll(double t) {
return 0;
}
virtual quaternion<double> local_orientation(double t) {
return AngleAxis2Quaternion(-t*(b-a), 1.0, 0.0, 0.0);
}
};
struct looping : public loopings {
looping() { a=(3*PI)/2.0; b=(7*PI)/2.0; clk=1.0; }
};
// WHIRL
struct whirl_track : public track_base_curved
{
double len;
double a;
double clk;
whirl_track() : a(0), len(0), clk(1) {}
void Degree(double f) { a=f; }
void Length(double f) { len=f; }
void Clk(double f) { clk=f; }
virtual double length() { return len; }
virtual Vector3d position(double t) {
return Vector3d(0.0, 0.0, t*len);
}
virtual Vector3d direction(double t) {
return Vector3d(0.0, 0.0, 1.0);
}
virtual Vector3d udirection(double t) {
return Vector3d(1.0, 0.0, 0.0);
}
virtual double roll(double t) {
return clk*sin(t*PI/2.0)*sin(t*PI/2.0)*a;
}
virtual quaternion<double> local_orientation(double t) {
return AngleAxis2Quaternion(roll(t), 0.0, 0.0, 1.0);
}
};
struct fullwhirl : public whirl_track {
fullwhirl() { a=2*PI; clk=1.0; }
};
struct fullwhirl_clockwise : public whirl_track {
fullwhirl_clockwise() { a=2*PI; clk=-1.0; }
};
struct halfwhirl : public whirl_track {
halfwhirl() { a=PI; clk=1.0; }
};
struct halfwhirl_clockwise : public whirl_track {
halfwhirl_clockwise() { a=PI; clk=-1.0; }
};
struct doublewhirl : public whirl_track {
doublewhirl() { a=4*PI; clk=1.0; }
};
struct doublewhirl_clockwise : public whirl_track {
doublewhirl_clockwise() { a=4*PI; clk=-1.0; }
};
struct train_track_desc
{
int type;
double arg1;
double arg2;
unsigned long f;
};
class train_track
{
List<track_base *> parts;
RenderableEntities *construction;
struct track_info
{
double length;
double before;
track_base *track;
};
int n_tracks;
int tid;
double track_length;
track_info *info;
void join_tracks() {
track_base *ptrack;
GLmatrix_double m;
m.Identity();
quaternion<double> q(1.0, 0.0, 0.0, 0.0);
parts.rewind();
for(int i=parts.size(); i; i--) {
ptrack = *parts;
ptrack->CS(m);
ptrack->QCS(q);
m = ptrack->coordinate_system(1.0);
q = ptrack->orientation(1.0);
++parts;
}
}
public:
train_track() : construction(0) {}
double length() { return track_length; }
void AddTrack(track_base *p) {
if(p) parts.push_back(p);
}
void operator +=(track_base *p) {
if(p) parts.push_back(p);
}
void AddTrack(int type, double arg1, double arg2, unsigned long flag) {
track_base *p = 0;
switch(type) {
case STRAIGHT:
p = new straight_track;
(*(straight_track *)p).Length(arg1);
break;
case HALFTURN_RIGHT:
p = new halfturn_right;
(*(halfturn_right *)p).Radius(arg1);
break;
case QUARTERTURN_RIGHT:
p = new quarterturn_right;
(*(quarterturn_right *)p).Radius(arg1);
break;
case UTURN_RIGHT:
p = new uturn_right;
(*(uturn_right *)p).Radius(arg1);
break;
case HALFTURN_LEFT:
p = new halfturn_left;
(*(halfturn_left *)p).Radius(arg1);
break;
case QUARTERTURN_LEFT:
p = new quarterturn_left;
(*(quarterturn_left *)p).Radius(arg1);
break;
case UTURN_LEFT:
p = new uturn_left;
(*(uturn_left *)p).Radius(arg1);
break;
case HALFTURN_UP:
p = new halfturn_up;
(*(halfturn_up *)p).Radius(arg1);
break;
case QUARTERTURN_UP:
p = new quarterturn_up;
(*(quarterturn_up *)p).Radius(arg1);
break;
case UTURN_UP:
p = new uturn_up;
(*(uturn_up *)p).Radius(arg1);
break;
case HALFTURN_DOWN:
p = new halfturn_down;
(*(halfturn_down *)p).Radius(arg1);
break;
case QUARTERTURN_DOWN:
p = new quarterturn_down;
(*(quarterturn_down *)p).Radius(arg1);
break;
case UTURN_DOWN:
p = new uturn_down;
(*(uturn_down *)p).Radius(arg1);
break;
case ASCEND:
p = new ascend;
(*(ascend *)p).Radius(arg1);
break;
case DESCEND:
p = new descend;
(*(descend *)p).Radius(arg1);
break;
case ASCEND_HIGH:
p = new ascend_high;
(*(ascend_high *)p).Radius(arg1);
break;
case DESCEND_HIGH:
p = new descend_high;
(*(descend_high *)p).Radius(arg1);
break;
case ASCEND_LOW:
p = new ascend_low;
(*(ascend_low *)p).Radius(arg1);
break;
case DESCEND_LOW:
p = new descend_low;
(*(descend_low *)p).Radius(arg1);
break;
case FULLWHIRL:
p = new fullwhirl;
(*(fullwhirl *)p).Length(arg1);
break;
case FULLWHIRL_CLOCKWISE:
p = new fullwhirl_clockwise;
(*(fullwhirl_clockwise *)p).Length(arg1);
break;
case HALFWHIRL:
p = new halfwhirl;
(*(halfwhirl *)p).Length(arg1);
break;
case HALFWHIRL_CLOCKWISE:
p = new halfwhirl_clockwise;
(*(halfwhirl_clockwise *)p).Length(arg1);
break;
case DOUBLEWHIRL:
p = new doublewhirl;
(*(doublewhirl *)p).Length(arg1);
break;
case DOUBLEWHIRL_CLOCKWISE:
p = new doublewhirl_clockwise;
(*(doublewhirl_clockwise *)p).Length(arg1);
break;
case LOOPING:
p = new looping;
(*(looping *)p).Radius(arg1);
break;
default:
return;
}
p->flag = flag;
AddTrack(p);
}
RenderableEntities* Construct() {
if(construction)
return construction;
construction = new RenderableEntities;
if(parts.size()==0)
return construction;
RenderableEntities tubes;
join_tracks();
info = new track_info[parts.size()];
n_tracks = parts.size();
tid = 0;
track_length = 0;
track_base *ptrack;
double l = 0;
parts.rewind();
for(int i=0; i<parts.size(); i++) {
ptrack = *parts;
construction->Add(ptrack->rails());
tubes.Add(ptrack->tube());
info[i].track = ptrack;
info[i].length = ptrack->length();
info[i].before = track_length;
track_length+=ptrack->length();
++parts;
}
construction->Add(tubes);
return construction;
}
RenderableEntities* Construct(int n, train_track_desc *desc) {
for(int i=n; i; i--, desc++)
AddTrack(desc->type, desc->arg1, desc->arg2, desc->f);
return Construct();
}
GLmatrix coordinate_system(double len) {
double l = len - floor(len/track_length)*track_length;
while(l<info[tid].before||l>(info[tid].before+info[tid].length))
if(l<info[tid].before) tid--;
else tid++;
l = (l-info[tid].before)/info[tid].length; // scale to <0,1>
GLmatrix_double q = (info[tid].track)->coordinate_system(l);
GLmatrix m;
for(int i=0; i<16; i++)
m[i] = (GLfloat)q[i];
return m;
}
quaternion<float> orientation(double len) {
double l = len - floor(len/track_length)*track_length;
while(l<info[tid].before||l>(info[tid].before+info[tid].length))
if(l<info[tid].before) tid--;
else tid++;
l = (l-info[tid].before)/info[tid].length; // scale to <0,1>
quaternion<double> q = (info[tid].track)->orientation(l);
return quaternion<float> ((float)re(q), (float)im1(q), (float)im2(q), (float)im3(q));
}
void Render() {
if(construction)
construction->Render();
}
};
#endif