View difference between Paste ID: 4hbJZd33 and DPaiBctp
SHOW: | | - or go back to the newest paste.
1
// g++ -std=c++11 main.cpp -lglut -lGLEW
2
3
#include <GL/glew.h>
4
#include <GL/glut.h>
5
6
/* Using the standard output for fprintf */
7
#include <iostream>
8
#include <functional>
9
#include <memory>
10
#include <vector>
11
#include <stdexcept>
12
13
#include <map>
14
#include <vector>
15
#include <cmath>
16
#include <algorithm>
17
#include <iterator>
18
#include <time.h>
19
20
using namespace std;
21
22
GLint attribute_coord3d, attribute_v_color;
23
GLuint vbo_triangle, vbo_triangle_colors;
24
GLuint program;
25
const int NUM_ITERATIONS = 5;
26
const int NUM_TRIANGLES = pow( 4.0, NUM_ITERATIONS );
27
int modelDrawn = 0;
28
29
30
struct vec3
31
{
32
    float x;
33
    float y;
34
    float z;
35
36
    vec3( float x1, float y1, float z1 ) : x( x1 ), y( y1 ), z( z1 )
37
    {
38
    }
39
40
    vec3( ) : x( 0 ), y( 0 ), z( 0 )
41
    {
42
    }
43
44
    vec3& operator+=(const vec3 & other )
45
    {
46
        x += other.x;
47
        y += other.y;
48
        z += other.z;
49
    }
50
51
    vec3 operator/=(const float)
52
    {
53
54
    }
55
56
    vec3 operator+(const vec3 & other ) const
57
    {
58
        return vec3( x + other.x, y + other.y, z + other.z );
59
    }
60
61
    vec3 operator/(const float &denom ) const
62
    {
63
        return vec3( x / denom, y / denom, z / denom );
64
    }
65
66
    vec3 operator*(const float mult)
67
    {
68
        return vec3( x*mult, y*mult, z * mult );
69
    }
70
71
    bool operator<(const vec3 & n ) const
72
    {
73
        if( x != n.x )
74
            return x < n.x;
75
        else if( y != n.y )
76
            return y < n.y;
77
        else if( z != n.z )
78
            return z < n.z;
79
        return length( ) < n.length( );
80
    }
81
82
    bool operator==(const vec3 & n ) const
83
    {
84
        return x == n.x && y == n.y && z == n.z;
85
    }
86
87
    float length( ) const
88
    {
89
        return sqrt( pow( x, 2 ) + pow( y, 2 ) + pow( z, 2 ) );
90
    }
91
92
    void Print( ) const
93
    {
94
        std::cout << "(" << x << "," << y << "," << z << ")" << std::endl;
95
    }
96
};
97
98
//container for gasket verts
99
std::vector<vec3> triangle_vertices;
100
std::vector<vec3> triangle_colors_vec;
101
102
float getRandom( float max, float min )
103
{
104
    return ((float(rand( ) ) / float(RAND_MAX ) ) * ( max - ( min ) ) ) + ( min );
105
}
106
107
float getVectorDistance( vec3 a, vec3 b )
108
{
109
    return sqrt( pow( ( a.x - b.x ), 2 ) + pow( ( a.y - b.y ), 2 ) + pow( ( a.z - b.z ), 2 ) );
110
}
111
112
vec3 randVector( );
113
114
115
struct Triangle
116
{
117
    vec3 a;
118
    vec3 b;
119
    vec3 c;
120
121
    Triangle( vec3 a1, vec3 b1, vec3 c1 ) : a( a1 ), b( b1 ), c( c1 )
122
    {
123
    }
124
};
125
126
vec3 getMidpoint( const vec3& a, const vec3& b )
127
{
128
    const float SCALE = 0.1;
129
130
    static std::map<std::pair<vec3, vec3>, vec3> memo;
131
132
133
    auto foundResult = memo.find( std::make_pair( a, b ) );
134
    if( foundResult != memo.end( ) )
135
    {
136
        return foundResult->second;
137
    }
138
139
    auto result = ( a + b ) / 2;
140
    auto variance = 0.1 * getVectorDistance( a, b );
141
    auto randX = getRandom( result.x + variance, result.x - variance );
142
    auto randY = getRandom( result.y + variance, result.y - variance );
143
    auto randZ = getRandom( result.z + variance, result.z - variance );
144
145
    result = vec3( randX, randY, randZ );
146
    memo.insert( std::make_pair( std::make_pair( a, b ), result ) );
147
    memo.insert( std::make_pair( std::make_pair( b, a ), result ) );
148
    return result;
149
150
}
151
152
void makeGasket( Triangle t, int count )
153
{
154
    if( count > 0 )
155
    {
156
        auto d = getMidpoint( t.a, t.b );
157
        auto e = getMidpoint( t.b, t.c );
158
        auto f = getMidpoint( t.a, t.c );
159
160
161
        makeGasket( Triangle( t.a, d, f ), count - 1 );
162
        makeGasket( Triangle( d, t.b, e ), count - 1 );
163
        makeGasket( Triangle( f, d, e ), count - 1 );
164
        makeGasket( Triangle( f, e, t.c ), count - 1 );
165
    }
166
    else
167
    {
168
        triangle_vertices.push_back( t.a );
169
        triangle_vertices.push_back( t.b );
170
        triangle_vertices.push_back( t.c );
171
172
    }
173
174
}
175
176
void createColors( )
177
{
178
    for( int i = 0; i < triangle_vertices.size( ); i++ )
179
    {
180
        float random = getRandom( 0.5, 1.0 );
181
        static std::map<vec3, float> randColor;
182
        auto foundResult = randColor.find( triangle_vertices[i] );
183
        if( foundResult != randColor.end( ) )
184
        {
185
            random = foundResult->second;
186
        }
187
        else
188
            randColor.insert( std::make_pair( triangle_vertices[i], random ) );
189
190
        triangle_colors_vec.push_back( vec3( random, random, random ) );
191
    }
192
193
}
194
195
vec3 triangle_verts[15000];
196
vec3 triangle_colors[15000];
197
198
void onDisplay( )
199
{
200
    srand( time( NULL ) );
201
    /* Clear the background as white */
202
    glClearColor( 0.0, 0.0, 0.0, 0.0 );
203
    glEnable( GL_DEPTH_TEST );
204
    glDepthFunc( GL_LESS );
205
    glCullFace( GL_FRONT );
206
    glEnable( GL_CULL_FACE );
207
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
208
    /* Tell OpenGL which program to use*/
209
    glUseProgram( program );
210
211
    if( modelDrawn == 0 )
212
    {
213
        modelDrawn = 1;
214
        vec3 verts[] ={
215
            vec3( 0.0, 1.0, 0.0 ),
216
            vec3( 0.943, -0.333, 0.0 ),
217
            vec3( -0.471, -0.333, 0.816 ),
218
            vec3( -0.471, -0.333, -0.816 )
219
        };
220
221
        Triangle initialTri = Triangle(
222
            verts[0],
223
            verts[2],
224
            verts[1]
225
            );
226
        Triangle initialTri2 = Triangle(
227
            verts[0],
228
            verts[1],
229
            verts[3]
230
            );
231
        Triangle initialTri3 = Triangle(
232
            verts[0],
233
            verts[3],
234
            verts[2]
235
            );
236
        Triangle initialTri4 = Triangle(
237
            verts[1],
238
            verts[2],
239
            verts[3]
240
            );
241
242
        makeGasket( initialTri, NUM_ITERATIONS );
243
        makeGasket( initialTri2, NUM_ITERATIONS );
244
        makeGasket( initialTri3, NUM_ITERATIONS );
245
        makeGasket( initialTri4, NUM_ITERATIONS );
246
247
        std::copy( triangle_vertices.begin( ), triangle_vertices.end( ), triangle_verts );
248
249
        createColors( );
250
251
        std::copy( triangle_colors_vec.begin( ), triangle_colors_vec.end( ), triangle_colors );
252
    }
253
254
    /* Setup vertex data */
255
    glBindBuffer( GL_ARRAY_BUFFER, vbo_triangle );
256
    glBufferData( GL_ARRAY_BUFFER, sizeof (triangle_verts ), triangle_verts, GL_STATIC_DRAW );
257
258
    auto attribute_coord3d = glGetAttribLocation( program, "coord3d" );
259
    glEnableVertexAttribArray( attribute_coord3d );
260
261
    /* Describe our vertices array to OpenGL (it can't guess its format automatically) */
262
    glVertexAttribPointer(
263
        attribute_coord3d, // attribute
264
        3, // number of elements per vertex, here (x,y,z)
265
        GL_FLOAT, // the type of each element
266
        GL_FALSE, // take our values as-is
267
        0, // no extra data between each position
268
        0 // vec3er to the C array
269
        );
270
271
    /* Push each element in buffer_vertices to the vertex shader */
272
    glBindBuffer( GL_ARRAY_BUFFER, vbo_triangle_colors );
273
    glBufferData( GL_ARRAY_BUFFER, sizeof (triangle_colors ), triangle_colors, GL_STATIC_DRAW );
274
275
    auto attribute_v_color = glGetAttribLocation( program, "v_color" );
276
    glEnableVertexAttribArray( attribute_v_color );
277
278
    glVertexAttribPointer(
279
        attribute_v_color, // attribute
280
        3, // number of elements per vertex, here (r,g,b)
281
        GL_FLOAT, // the type of each element
282
        GL_FALSE, // take our values as-is
283
        0, // no extra data between each position
284
        0 // offset of first element
285
        );
286
287
    glDrawArrays( GL_TRIANGLES, 0, NUM_TRIANGLES * 3 * 4 );
288
    glDisableVertexAttribArray( attribute_coord3d );
289
    glDisableVertexAttribArray( attribute_v_color );
290
291
    /* Display the result */
292
    glutSwapBuffers( );
293
}
294
295
void rotate( int value )
296
{
297
    float angle = 0.0175; // 1 degree
298
    //float angle = glutGet(GLUT_ELAPSED_TIME) / 1000.0 * 0.001;
299
300
    float rotation_matrix[] ={
301
        cosf( angle ), 0, sinf( angle ),
302
        0, 1, 0,
303
        -1.0 * sinf( angle ), 0, cosf( angle ),
304
305
    };
306
    float rotation_matrix_x[] ={
307
        1, 0, 0,
308
        0, cosf( angle ), -1.0 * sinf( angle ),
309
        0, sinf( angle ), cosf( angle ),
310
311
    };
312
    float rotation_matrix_z[] ={
313
        cosf( angle ), -1.0 * sin( angle ), 0,
314
        sinf( angle ), cosf( angle ), 0,
315
        0, 0, 1,
316
    };
317
318
    vec3 tempVec;
319
    for( int i = 0; i < triangle_vertices.size( ); i++ )
320
    {
321
        tempVec.x = rotation_matrix[0] * triangle_verts[i].x + rotation_matrix[1] * triangle_verts[i].y + rotation_matrix[2] * triangle_verts[i].z;
322
        tempVec.y = rotation_matrix[3] * triangle_verts[i].x + rotation_matrix[4] * triangle_verts[i].y + rotation_matrix[5] * triangle_verts[i].z;
323
        tempVec.z = rotation_matrix[6] * triangle_verts[i].x + rotation_matrix[7] * triangle_verts[i].y + rotation_matrix[8] * triangle_verts[i].z;
324
        triangle_verts[i] = tempVec;
325
    }
326
    glutTimerFunc( 10, rotate, 1 );
327
    glutPostRedisplay( );
328
}
329
330
void CheckStatus( GLuint obj )
331
{
332
    GLint status = 0;
333
    if( glIsShader( obj ) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
334
    if( glIsProgram( obj ) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
335
    if( status == GL_TRUE ) return;
336
337
    GLint len = 0;
338
    if( glIsShader( obj ) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
339
    if( glIsProgram( obj ) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
340
341
    vector< char > log( len );
342
    if( glIsShader( obj ) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
343
    if( glIsProgram( obj ) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
344
    if( glIsShader( obj ) ) glDeleteShader( obj );
345
    if( glIsProgram( obj ) ) glDeleteProgram( obj );
346
    throw runtime_error( string( log.begin( ), log.end( ) ) );
347
}
348
349
GLuint LoadShader( GLenum type, const string& aShaderSrc )
350
{
351
    GLuint shader = glCreateShader( type );
352
    const char* srcPtr = aShaderSrc.c_str( );
353
    glShaderSource( shader, 1, &srcPtr, NULL );
354
    glCompileShader( shader );
355
    CheckStatus( shader );
356
    return shader;
357
}
358
359
GLuint LoadProgram( const string& aVertSrc, const string& aFragSrc )
360
{
361
    GLuint vert = LoadShader( GL_VERTEX_SHADER, aVertSrc );
362
    GLuint frag = LoadShader( GL_FRAGMENT_SHADER, aFragSrc );
363
    GLuint program = glCreateProgram( );
364
    glAttachShader( program, vert );
365
    glAttachShader( program, frag );
366
    glLinkProgram( program );
367
    CheckStatus( program );
368-
    // delete shaders here?
368+
369
}
370
371
#define GLSL(version, shader)  "#version " #version "\n" #shader
372
373
const GLchar* vert = GLSL
374
    (
375
    120,
376
    attribute vec3 coord3d;
377
    attribute vec3 v_color;
378
    varying vec3 f_color;
379
    void main( void )
380
    {
381
        gl_Position = vec4( coord3d, 1.0 );
382
        f_color = v_color;
383-
    gl_Position = vec4( coord3d, 1.0 );
383+
384
);
385
386
const GLchar* frag = GLSL
387
    (
388
    120,
389
    varying vec3 f_color;
390
    void main( void )
391
    {
392
        gl_FragColor = vec4( f_color.x, f_color.y, f_color.z, 1.0 );
393
    }
394-
    gl_FragColor = vec4( f_color.x, f_color.y, f_color.z, 1.0 );
394+
395
396
int main( int argc, char* argv[] )
397
{
398
    /* Glut-related initialising functions */
399
    glutInit( &argc, argv );
400
    glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
401
    glutInitWindowSize( 640, 480 );
402
    glutCreateWindow( "Hello Triangle!" );
403
404
    /* Extension wrangler initialising */
405
    GLenum glew_status = glewInit( );
406
    if( glew_status != GLEW_OK )
407
    {
408
        fprintf( stderr, "Error: %s\n", glewGetErrorString( glew_status ) );
409
        return EXIT_FAILURE;
410
    }
411
412
    /* When all init functions runs without errors,
413
    the program can initialise the resources */
414
    try
415
    {
416
        program = LoadProgram( vert, frag );
417
418
        glGenBuffers( 1, &vbo_triangle );
419
        glGenBuffers( 1, &vbo_triangle_colors );
420
421
        glutDisplayFunc( onDisplay );
422
        //glutIdleFunc( idle );
423
424
        glutTimerFunc( 10, rotate, 1 );
425
        glutMainLoop( );
426
    }
427
    catch( std::exception& e )
428
    {
429
        std::cerr << e.what( );
430
    }
431
    return EXIT_SUCCESS;
432
}