Blob Blame Raw

#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();
}