3 #include <msp/gl/misc.h>
13 Track3D::Track3D(Track &t, unsigned q):
16 varray((GL::NORMAL3, GL::VERTEX3)),
22 void Track3D::set_quality(unsigned q)
28 void Track3D::get_bounds(float angle, Point &minp, Point &maxp) const
30 const Point &pos=track.get_position();
31 float rot=track.get_rotation();
36 minp.x=maxp.x=c*pos.x-s*pos.y;
37 minp.y=maxp.y=s*pos.x+c*pos.y;
39 float c2=cos(rot-angle);
40 float s2=sin(rot-angle);
42 for(vector<Point>::const_iterator i=border.begin(); i!=border.end(); ++i)
44 float x=c*pos.x-s*pos.y + c2*i->x-s2*i->y;
45 float y=s*pos.x+c*pos.y + s2*i->x+c2*i->y;
47 minp.x=min(minp.x, x);
48 minp.y=min(minp.y, y);
49 maxp.x=max(maxp.x, x);
50 maxp.y=max(maxp.y, y);
54 void Track3D::render()
58 glPushName((unsigned)this);
61 glColor4f(0.25*color.r, 0.25*color.g, 0.25*color.b, 1);
62 glDrawElements(GL_QUADS, base_seq.size(), GL_UNSIGNED_INT, &base_seq[0]);
65 glColor4f(0.85*color.r, 0.85*color.g, 0.85*color.b, 1);
66 glDrawElements(GL_QUADS, rail_seq.size(), GL_UNSIGNED_INT, &rail_seq[0]);
73 void Track3D::render_endpoints()
77 const Point &pos=track.get_position();
78 const Track::EndpointSeq &endpoints=track.get_endpoints();
79 for(Track::EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
81 GL::set(GL_CULL_FACE, i->link);
83 glColor4f(0.5, 0, 1, 0.5);
85 glColor4f(1, 0, 0.5, 0.5);
91 glVertex3f(i->pos.x-s*0.025, i->pos.y+c*0.025, 0);
92 glVertex3f(i->pos.x+s*0.025, i->pos.y-c*0.025, 0);
93 glVertex3f(i->pos.x+s*0.025, i->pos.y-c*0.025, pos.z+i->pos.z+0.02);
94 glVertex3f(i->pos.x-s*0.025, i->pos.y+c*0.025, pos.z+i->pos.z+0.02);
101 void Track3D::render_route(int route)
106 if(route>=0 && static_cast<unsigned>(route)<route_seq.size())
107 glDrawElements(GL_QUADS, route_seq[route].size(), GL_UNSIGNED_INT, &route_seq[route][0]);
110 for(unsigned i=0; i<route_seq.size(); ++i)
111 glDrawElements(GL_QUADS, route_seq[i].size(), GL_UNSIGNED_INT, &route_seq[i][0]);
117 void Track3D::prepare_render()
119 const Point &pos=track.get_position();
120 float rot=track.get_rotation();
123 glTranslatef(pos.x, pos.y, pos.z);
124 glRotatef(rot*180/M_PI, 0, 0, 1);
127 void Track3D::build_object()
130 RefPtr<GL::VertexArrayBuilder> builder=varray.modify();
135 route_seq.resize(track.get_n_routes());
137 const Track::PartSeq &parts=track.get_parts();
139 for(Track::PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
140 build_part(*i, *builder, index);
143 void Track3D::build_part(const Track::Part &part, GL::VertexArrayBuilder &va_builder, unsigned &base_index)
145 static vector<Point> profile;
148 profile.push_back(Point(0, -0.02, 0));
149 profile.push_back(Point(0, -0.014, 0.008));
150 profile.push_back(Point(0, -0.014, 0.008));
151 profile.push_back(Point(0, 0.014, 0.008));
152 profile.push_back(Point(0, 0.014, 0.008));
153 profile.push_back(Point(0, 0.02, 0));
154 for(unsigned i=0; i<2; ++i)
156 profile.push_back(Point(0, -0.009+i*0.017, 0.008));
157 profile.push_back(Point(0, -0.009+i*0.017, 0.0103));
158 profile.push_back(Point(0, -0.009+i*0.017, 0.0103));
159 profile.push_back(Point(0, -0.008+i*0.017, 0.0103));
160 profile.push_back(Point(0, -0.008+i*0.017, 0.0103));
161 profile.push_back(Point(0, -0.008+i*0.017, 0.008));
163 profile.push_back(Point(0, -0.002, 0.012));
164 profile.push_back(Point(0, 0.002, 0.012));
166 static unsigned psize=profile.size();
168 const float &radius=part.radius;
169 const float &x=part.x;
170 const float &y=part.y;
171 const float &length=part.length;
172 const float &dir=part.dir;
177 nsegs=(unsigned)(part.length*(1<<quality))+1;
178 Point center(x-sin(dir)*radius, y+cos(dir)*radius, 0);
179 float r=fabs(radius);
180 float start=((radius<0)?M_PI:0)+dir;
181 float angle=(radius<0)?-length:length;
182 int inv=(radius<0)?-1:1;
183 for(unsigned i=0; i<=nsegs; ++i)
185 float a=start+i*angle/nsegs;
189 for(unsigned j=0; j<profile.size(); ++j)
192 float dy=profile[k+1].y-profile[k].y;
193 float dz=profile[k+1].z-profile[k].z;
194 float d=sqrt(dy*dy+dz*dz);
195 va_builder.normal(s*dz/d, -c*dz/d, dy/d);
197 Point p(center.x+s*(r-profile[j].y*inv), center.y-c*(r-profile[j].y*inv), profile[j].z+i*track.get_slope()/nsegs);
198 va_builder.vertex(p.x, p.y, p.z);
209 for(unsigned i=0; i<2; ++i)
211 for(unsigned j=0; j<profile.size(); ++j)
214 float dy=profile[k+1].y-profile[k].y;
215 float dz=profile[k+1].z-profile[k].z;
216 float d=sqrt(dy*dy+dz*dz);
217 va_builder.normal(s*dz/d, -c*dz/d, dy/d);
219 float len=(part.dead_end && i==1 && j>=6) ? length/2 : length;
220 Point p(x+c*len*i-s*profile[j].y, y+s*len*i+c*profile[j].y, profile[j].z+i*track.get_slope());
221 va_builder.vertex(p.x, p.y, p.z);
228 for(unsigned i=0; i<nsegs; ++i)
230 for(unsigned j=0; j<3; ++j)
232 base_seq.push_back(base_index+i*psize+j*2);
233 base_seq.push_back(base_index+(i+1)*psize+j*2);
234 base_seq.push_back(base_index+(i+1)*psize+1+j*2);
235 base_seq.push_back(base_index+i*psize+1+j*2);
237 for(unsigned j=3; j<9; ++j)
239 rail_seq.push_back(base_index+i*psize+j*2);
240 rail_seq.push_back(base_index+(i+1)*psize+j*2);
241 rail_seq.push_back(base_index+(i+1)*psize+1+j*2);
242 rail_seq.push_back(base_index+i*psize+1+j*2);
244 route_seq[part.route].push_back(base_index+i*psize+18);
245 route_seq[part.route].push_back(base_index+(i+1)*psize+18);
246 route_seq[part.route].push_back(base_index+(i+1)*psize+19);
247 route_seq[part.route].push_back(base_index+i*psize+19);
250 base_index+=(nsegs+1)*psize;
253 } // namespace Marklin