#include <cstdlib>
#include <iostream>
#include <GL/gl.h>
#include "scene.h"
#include "simulator.h"
#include "model.h"
Scene::Scene():
angles(45.0, 0.0, 30.0),
offset(0, 0, -100),
stars_seed(rand()),
time(),
time_forward(0.0),
time_backward(100.0),
time_speed(10.0),
model_angle(),
model(),
simulator(),
tool_dir(0, 0, -1),
tool(),
collider(),
move_tool(true),
rotate_model(true)
{ }
Scene::~Scene() { }
Vector4 Scene::color_by_time(Real t) {
return t <= time
? color_by_time_past(t)
: color_by_time_future(t);
}
Vector4 Scene::color_by_time_past(Real t) {
Vector4 far_past(0.33, 0.33, 0.33, 0);
Vector4 past(1, 1, 0.33, 1);
Vector4 color;
if (time_backward <= 0.0001 || t < time - time_backward)
return far_past;
Real l = (time - t)/time_backward;
Real k = 1 - l;
for(int i = 0; i < 4; ++i)
color.c[i] = past.c[i]*k + far_past.c[i]*l;
return color;
}
Vector4 Scene::color_by_time_future(Real t) {
Vector4 future(1, 1, 0.33, 1);
Vector4 far_future(0.166, 0.166, 0.66, 0);
Vector4 color;
if (time_forward <= 0.0001 || time + time_forward < t)
return far_future;
Real l = (t - time)/time_forward;
Real k = 1 - l;
for(int i = 0; i < 4; ++i)
color.c[i] = future.c[i]*k + far_future.c[i]*l;
return color;
}
void Scene::update(Real dt) {
time += time_speed*dt;
if (time < 0 || track.points.empty()) {
time = 0;
if (time_speed < 0) time_speed = 0;
} else
if (time > track.points.back().time) {
time = track.points.back().time;
if (time_speed > 0) time_speed = 0;
}
int index = track.index_by_time(time);
if (index > 0) {
const TrackPoint &p0 = track.points[index-1];
const TrackPoint &p1 = track.points[index];
Real l = p1.duration > 1e-5 ? (p0.time - time)/p1.duration : 0.5;
TrackPoint p = TrackPoint::median(l, p0, p1);
//std::cout << p.angle << std::endl;
if (move_tool) {
Real a = p.angle*(M_PI/180);
Real s = sin(a);
Real c = cos(a);
tool_pos = p.real_pos;
tool_dir = Vector3(0, p.position.z*s, -p.position.z*c).norm();
}
if (rotate_model) model_angle = p.angle;
if (simulator) simulator->scroll_to(index);
}
}
Real Scene::random()
{ return (rand()/(Real)RAND_MAX - 0.5)*2; }
void Scene::draw_stars() {
int seed = rand();
srand(stars_seed);
glEnable(GL_FOG);
glFogf(GL_FOG_DENSITY, 0.002f);
glColor4d(1, 1, 1, 1);
glBegin(GL_POINTS);
for(int i = 0; i < 1000; ++i) {
glVertex3d(
random()*1000.0,
random()*1000.0,
random()*1000.0 );
}
glEnd();
glDisable(GL_FOG);
srand(seed);
}
void Scene::draw_axes() {
glBegin(GL_LINES);
glColor3d(1, 0, 0);
glVertex3d(0, 0, 0);
glVertex3d(50, 0, 0);
glColor3d(0, 1, 0);
glVertex3d(0, 0, 0);
glVertex3d(0, 50, 0);
glColor3d(0, 0, 1);
glVertex3d(0, 0, 0);
glVertex3d(0, 0, 50);
glEnd();
}
void Scene::draw_track() {
int index = track.index_by_time(time);
if (index <= 0) return;
const TrackPoint &p0 = track.points[index-1];
const TrackPoint &p1 = track.points[index];
Real l = p1.duration > 1e-5 ? (p0.time - time)/p1.duration : 0.5;
TrackPoint p = TrackPoint::median(l, p0, p1);
glBegin(GL_LINE_STRIP);
for(int i = 0; i < index; ++i) {
glColor4dv( color_by_time_past(track.points[i].time).c );
glVertex3dv( track.points[i].real_pos.c );
}
glColor4dv( color_by_time_past(p.time).c );
glVertex3dv( p.real_pos.c );
glEnd();
glBegin(GL_LINE_STRIP);
for(int i = (int)track.points.size() - 1; i >= index; --i) {
glColor4dv( color_by_time_future(track.points[i].time).c );
glVertex3dv( track.points[i].real_pos.c );
}
glColor4dv( color_by_time_future(p.time).c );
glVertex3dv( p.real_pos.c );
glEnd();
}
void Scene::draw() {
glPushMatrix();
glTranslated(offset.x, offset.y, offset.z);
glRotated(-90, 1, 0, 0);
glRotated(angles.y, 0, 1, 0);
glRotated(angles.x, 1, 0, 0);
glRotated(angles.z, 0, 0, 1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
draw_stars();
draw_axes();
glPushMatrix();
glRotated(-model_angle, 1, 0, 0);
if (model) model->draw();
if (simulator) simulator->draw();
if (tool) tool->draw(tool_pos, tool_dir);
glRotated(-model_angle, 1, 0, 0);
draw_track();
glPopMatrix();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
glPopMatrix();
}