Copyright 2008-2014 Matus Chochlik. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <cmath>
#include <cassert>
#include <ctime>
namespace oglplus {
class GraphExample : public Example
{
private:
Context gl;
Uniform<Mat4f> projection_matrix;
Uniform<Mat4f> camera_matrix;
const GLuint node_count;
GLuint edge_count;
static double nrand(void)
{
return 2.0*(double(std::rand())/RAND_MAX - 0.5);
}
CubicBezierLoop<Vec3f, double> cam_path;
CubicBezierLoop<Vec3f, double> tgt_path;
static std::vector<Vec3f> make_cam_path_cps(void)
{
const Vec3f _points[6] = {
Vec3f(-40.0f, -50.0f, -50.0f),
Vec3f( 40.0f, 0.0f, -60.0f),
Vec3f( 60.0f, 30.0f, 50.0f),
Vec3f(-20.0f, 50.0f, 55.0f),
Vec3f(-30.0f, 30.0f, 0.0f),
Vec3f(-60.0f, 4.0f, -30.0f)
};
return std::vector<Vec3f>(_points, _points+6);
}
static std::vector<Vec3f> make_tgt_path_cps(void)
{
const Vec3f _points[6] = {
Vec3f(-10.0f, 0.0f, -10.0f),
Vec3f( 10.0f, 10.0f, -10.0f),
Vec3f( 10.0f, 0.0f, 10.0f),
Vec3f(-10.0f, - 5.0f, 15.0f),
Vec3f(-10.0f, - 3.0f, 0.0f),
Vec3f(-10.0f, 0.0f, -10.0f)
};
return std::vector<Vec3f>(_points, _points+6);
}
public:
GraphExample(void)
: prog()
, projection_matrix(prog)
, camera_matrix(prog)
, node_count(512)
, edge_count(0)
, cam_path(make_cam_path_cps())
, tgt_path(make_tgt_path_cps())
{
std::srand(std::time(0));
vs.Source(
"#version 330\n"
"uniform mat4 ProjectionMatrix, CameraMatrix;"
"in vec4 Position;"
"void main(void)"
"{"
" gl_Position = "
" ProjectionMatrix *"
" CameraMatrix *"
" Position;"
" gl_PointSize = 4.0 * gl_Position.w / gl_Position.z;"
"}"
);
vs.Compile();
fs.Source(
"#version 330\n"
"out vec4 fragColor;"
"void main(void)"
"{"
" fragColor = vec4(0.0, 0.0, 0.0, 1.0);"
"}"
);
fs.Compile();
prog.AttachShader(vs);
prog.AttachShader(fs);
prog.Link();
prog.Use();
projection_matrix.BindTo("ProjectionMatrix");
camera_matrix.BindTo("CameraMatrix");
graph.Bind();
std::vector<GLfloat> positions(node_count * 3);
{
GLuint k = 0;
for(GLuint p=0; p!=node_count; ++p)
{
positions[k++] = nrand() *120.0;
positions[k++] = nrand() * 5.0;
positions[k++] = nrand() *120.0;
}
assert(k == positions.size());
VertexArrayAttrib vert_attr(prog, "Position");
vert_attr.Setup<GLfloat>(3).
Enable();
}
{
std::vector<GLuint> edge_data;
edge_data.reserve(node_count * 6);
for(GLuint i=0; i!=node_count; ++i)
{
positions[i*3+0],
positions[i*3+1],
positions[i*3+2]
);
float min_dist = 1000.0f;
GLuint m = i;
for(GLuint j=i+1; j!=node_count; ++j)
{
positions[j*3+0],
positions[j*3+1],
positions[j*3+2]
);
float dist = Distance(pi, pj);
if(min_dist > 1.0 && min_dist > dist)
{
min_dist = dist;
m = j;
}
}
min_dist *= 2.0f;
GLuint done = 0;
for(GLuint j=i+1; j!=node_count; ++j)
{
positions[j*3+0],
positions[j*3+1],
positions[j*3+2]
);
float dist = Distance(pi, pj);
if(min_dist > dist)
{
float x = dist/min_dist;
if(std::pow(nrand(), 2.0) >= x)
{
edge_data.push_back(i);
edge_data.push_back(j);
++done;
}
}
}
if(done == 0)
{
if(i != m)
{
edge_data.push_back(i);
edge_data.push_back(m);
}
}
}
assert(edge_data.size() % 2 == 0);
edge_count = edge_data.size();
positions.clear();
}
gl.ClearColor(0.9f, 0.9f, 0.8f, 0.0f);
gl.ClearDepth(1.0f);
}
void Reshape(GLuint width, GLuint height)
{
gl.Viewport(width, height);
prog.Use();
projection_matrix.Set(
Degrees(70),
double(width)/height,
1, 200
)
);
}
{
gl.Clear().ColorBuffer().DepthBuffer();
camera_matrix.Set(
cam_path.Position(time / 9.0),
tgt_path.Position(time / 7.0)
)
);
gl.DrawElements(
edge_count,
);
}
{
return time < 60.0;
}
};
void setupExample(ExampleParams& ){ }
std::unique_ptr<ExampleThread> makeExampleThread(
Example& ,
unsigned ,
const ExampleParams&
){ return std::unique_ptr<ExampleThread>(); }
std::unique_ptr<Example> makeExample(const ExampleParams& )
{
return std::unique_ptr<Example>(new GraphExample);
}
}