Projekt

Obecné

Profil

Stáhnout (18.6 KB) Statistiky
| Větev: | Tag: | Revize:
1
#include "scene.hpp"
2

    
3
#include "../curvedataserver.h"
4

    
5
const int Scene::TRAJECTORY_I = 0;
6
const int Scene::SPHERE_I = 1;
7
const int Scene::SPHERE_II = 2;
8
const int Scene::FIRST_ARROW_I = 3;
9
const float Scene::FIRST_ARROW_WIDTH_SCALING = 750.0f;
10
const float Scene::SECOND_ARROW_WIDTH_SCALING = 400.0f;
11
const QVector3D Scene::MODIFY_LIGHT_POSITION = QVector3D(0, 0, 0);
12
const int Scene::ROTATE_REDUCTION = 25;
13

    
14
Scene::Scene(QWidget *parent): QOpenGLWidget(parent)
15
{
16
    xAngle = 0;
17
    yAngle = 0;
18
    eyeAngle = 45;
19
    shaderProgram = NULL;
20
    
21
    // Vytvoreni grafickych prvku.
22
    elements[TRAJECTORY_I] = (Element *) new Trajectory();
23
    elements[SPHERE_I] = (Element *) new Sphere(true);
24
    elements[SPHERE_II] = (Element *) new Sphere(false);
25
    elements[FIRST_ARROW_I] = (Element *) new Arrow(true);
26
    elements[FIRST_ARROW_I + 1] = (Element *) new Arrow(false);
27
    elements[FIRST_TYPE_WALL_I] = (Element *) new Wall(Wall::TYPE::FLOOR);
28
    elements[FIRST_TYPE_WALL_I + 1] = (Element *) new Wall(Wall::TYPE::CEILING);
29
    elements[FIRST_TYPE_WALL_I + 2] = (Element *) new Wall(Wall::TYPE::SIDE);
30
    
31
    // Cesty k vyuzivanym texturam.
32
    texturePath[0] = tr(":/img/floor.png");
33
    texturePath[1] = tr(":/img/ceiling_1013.png");
34
    texturePath[2] = tr(":/img/tile.png");
35
    
36
    // Barva pozadi, zde je zbytecne nastavovat alfa kanal.
37
    backgroundColor = QVector3D(0.702f, 1, 1);
38
    // Barva tubusu predstavujici krivku.
39
    colorValues[0] = QVector4D(1, 0.737f, 0.231f, 0.7f);
40
    // Barva koule, která se pohybuje.
41
    colorValues[1] = QVector4D(0, 0.4f, 1, 0.7f);
42
    //Barva statické koule
43
    colorValues[2] = QVector4D(0, 0.8f, 0.4f, 0.0f);
44
    // Barva prvni (dulezitejsi) krivky.
45
    colorValues[3] = QVector4D(0, 1, 0, 1);
46
    // Barva druhe (mene dulezite) krivky. Zmena pruhlednosti = zmena alfa kanalu.
47
    colorValues[4] = QVector4D(1, 0, 0, 0.75f);
48
}
49

    
50
Scene::~Scene()
51
{
52
    clear();
53
    // Uvolnit zbyvajici alokovanou pamet (uz zbyvaji pouze graficke prvky, ktere
54
    // jsou vytvoreny na zacatku a vyuzivany po celou dobu behu programu - nejsou
55
    // nejak napojeny na jadro OpenGL, hodnoty v techto objektech se vzdy
56
    // prekopiruji do celkoveho pole, ktere se pak ulozi do bufferu).
57
    for (int i = 0; i < FIRST_TYPE_WALL_I + 3; i++)
58
    {
59
        delete elements[i];
60
    }
61
}
62

    
63
void Scene::setCurve(QList<QVector4D> curve, CurveDataServer * cdServer)
64
{
65
    // Vyhledani minimalnich a maximalnich souradnic.
66
    QList<QVector3D> curve3d;
67
    QVector3D minimum = curve.at(0).toVector3D();
68
    QVector3D maximum = curve.at(0).toVector3D();
69
    int itemCount = curve.size();
70
#if 0
71
    for (int i = 1; i < curve.count(); i++)
72
    {
73
        if (curve.at(i).x() < minimum.x())
74
        {
75
            minimum.setX(curve.at(i).x());
76
        }
77
        else if (curve.at(i).x() > maximum.x())
78
        {
79
            maximum.setX(curve.at(i).x());
80
        }
81
        if (curve.at(i).y() < minimum.y())
82
        {
83
            minimum.setY(curve.at(i).y());
84
        }
85
        else if (curve.at(i).y() > maximum.y())
86
        {
87
            maximum.setY(curve.at(i).y());
88
        }
89
        if (curve.at(i).z() < minimum.z())
90
        {
91
            minimum.setZ(curve.at(i).z());
92
        }
93
        else if (curve.at(i).z() > maximum.z())
94
        {
95
            maximum.setZ(curve.at(i).z());
96
        }
97
    }
98
#else
99
    //max a min nepocitat podle kriky, ale mit vzdycky maximalni rozsah
100
    minimum = QVector3D(-3200,-3200,0);
101
    maximum = QVector3D(3200,3200,9000);
102
#endif
103

    
104
    // Posunout stred krivky do pocatku soustavy souradnic (kvuli ruznym upravam).
105
    // Uchovat stred puvodne umistene krivky kvuli prichozim bodum predstavujici
106
    // pozici koule (souradnice tohoto bodu se take musi upravit pro presne zobrazeni).
107
    center = Sphere::middlePoint(minimum, maximum);
108
    minimum -= center;
109
    maximum -= center;
110
    curve3d.clear();
111
    if (itemCount > MAX_CURVE_SIZE)
112
        itemCount = MAX_CURVE_SIZE;
113
    for (int i = 0; i < itemCount; i++)
114
    {
115
        curve3d.append(curve[i].toVector3D() - center);
116
    }
117
    
118
    // Zjisteni a nastaveni optimalni polohy kamery na ose Z.
119
    QVector3D marginForTube(Trajectory::MAX_RADIUS, Trajectory::MAX_RADIUS, Trajectory::MAX_RADIUS);
120
    QVector3D marginForSphere(Sphere::getMaxRadius(), Sphere::getMaxRadius(), Sphere::getMaxRadius());
121
    float tg = tan((eyeAngle / 2) * M_PI / 180);
122
    QVector3D heights = QVector3D(maximum + marginForTube + marginForSphere) / tg;
123
    camera.set(QVector3D(0, 0, maximum.z() + max(heights.x(), heights.y())));
124
    
125
    // Nastaveni atributu vykreslovanych objektu.
126
    ((Trajectory *) (elements[TRAJECTORY_I]))->setNewCurve(curve3d, minimum.z(), maximum.z());
127
    ((Sphere *) (elements[SPHERE_I]))->setRangeZ(minimum.z(), maximum.z());
128
#ifdef USE_STATIC_SPHERE
129
    ((Sphere *) (elements[SPHERE_II]))->setRangeZ(minimum.z(), maximum.z());
130
#else
131
    ((Sphere *) (elements[SPHERE_II]))->setRangeZ(0,0);
132
    ((Sphere *) (elements[SPHERE_II]))->setPosition(QVector3D(0,0,-3200));
133
#endif
134
    for (int i = FIRST_TYPE_WALL_I; i < ELEMENT_COUNT; i++)
135
    {
136
        ((Wall *) (elements[i]))->setData(minimum, maximum, ((Sphere *) (elements[SPHERE_I]))->getMaxRadius());
137
    }
138
    
139
    // Upravit data v bufferu.
140
    updateBufferData();
141
    
142
    // Prenastavit pozici svetla.
143
    shaderProgram->bind();
144
    shaderProgram->setUniformValue(lightLocation, camera.getPosition() + MODIFY_LIGHT_POSITION);
145
    int colorLocation = shaderProgram->uniformLocation("un_Color[0]");
146
    shaderProgram->setUniformValue(colorLocation, colorValues[0]);
147
    shaderProgram->release();
148
    
149
    // Vynulovat pripadnou rotaci.
150
    setXAngle(0); setYAngle(0);
151
    
152
    // Vykreslit.
153
    update();
154

    
155
    if (cdServer) {
156
        cdServer->sendNewCurve(curve3d);
157
    }
158
}
159

    
160
void Scene::setSphereData(const QVector3D &position, const QVector3D &fArrow, const QVector3D &sArrow)
161
{
162
    // Zmenit vektory pro prvni a druhou sipku.
163
    firstArrow = fArrow;
164
    secondArrow = sArrow;
165
    // Zmenit pozici koule.
166
    ((Sphere *) (elements[SPHERE_I]))->setPosition(position - center);
167
    // Prekreslit scenu.
168
    update();
169
}
170

    
171
void Scene::setTestSphereData(const QVector3D &position)
172
{
173
#ifdef USE_STATIC_SPHERE
174
    // Zmenit pozici koule.
175
    ((Sphere *) (elements[SPHERE_II]))->setPosition(position - center);
176
    // Prekreslit scenu.
177
    update();
178
#endif
179
}
180

    
181
QVector3D Scene::getArrow(bool first)
182
{
183
    return first ? firstArrow : secondArrow;
184
}
185

    
186
void Scene::setArrow(bool first, QVector3D vector)
187
{
188
    first ? firstArrow = vector : secondArrow = vector;
189
}
190

    
191
void Scene::setTubusColor(QVector4D color)
192
{
193
    colorValues[0] = color;
194
}
195

    
196
void Scene::addSphereData(QVector3D position, const bool start, const bool finish)
197
{
198
    QVector3D minimum = QVector3D(-3200,-3200,0);
199
    QVector3D maximum = QVector3D(3200,3200,9000);
200

    
201
    // Posunout stred krivky do pocatku soustavy souradnic (kvuli ruznym upravam).
202
    // Uchovat stred puvodne umistene krivky kvuli prichozim bodum predstavujici
203
    // pozici koule (souradnice tohoto bodu se take musi upravit pro presne zobrazeni).
204
    center = Sphere::middlePoint(minimum, maximum);
205
    minimum -= center;
206
    maximum -= center;
207
    //position -= center;
208

    
209
    if (start) {
210
        // Zjisteni a nastaveni optimalni polohy kamery na ose Z.
211
        QVector3D marginForTube(Trajectory::MAX_RADIUS, Trajectory::MAX_RADIUS, Trajectory::MAX_RADIUS);
212
        QVector3D marginForSphere(Sphere::getMaxRadius(), Sphere::getMaxRadius(), Sphere::getMaxRadius());
213
        float tg = tan((eyeAngle / 2) * M_PI / 180);
214
        QVector3D heights = QVector3D(maximum + marginForTube + marginForSphere) / tg;
215
        camera.set(QVector3D(0, 0, maximum.z() + max(heights.x(), heights.y())));
216

    
217
        // Nastaveni atributu vykreslovanych objektu.
218
    }
219
    ((Trajectory *) (elements[TRAJECTORY_I]))->addNewPointToCurve(position, start, finish);
220
    if (start) {
221
        ((Sphere *) (elements[SPHERE_I]))->setRangeZ(minimum.z(), maximum.z());
222
        ((Sphere *) (elements[SPHERE_II]))->setRangeZ(minimum.z(), maximum.z());
223
        for (int i = FIRST_TYPE_WALL_I; i < ELEMENT_COUNT; i++)
224
        {
225
            ((Wall *) (elements[i]))->setData(minimum, maximum, ((Sphere *) (elements[SPHERE_I]))->getMaxRadius());
226
        }
227
    }
228

    
229
    // Upravit data v bufferu.
230
    updateBufferData();
231

    
232
    // Prenastavit pozici svetla.
233
    shaderProgram->bind();
234
    shaderProgram->setUniformValue(lightLocation, camera.getPosition() + MODIFY_LIGHT_POSITION);
235
    int colorLocation = shaderProgram->uniformLocation("un_Color[0]");
236
    shaderProgram->setUniformValue(colorLocation, colorValues[0]);
237
    shaderProgram->release();
238

    
239
    // Vynulovat pripadnou rotaci.
240
    setXAngle(0); setYAngle(0);
241

    
242
    // Vykreslit.
243
    update();
244
}
245

    
246
QSize Scene::minimumSizeHint() const
247
{
248
    return QSize(100, 100);
249
}
250

    
251
QSize Scene::sizeHint() const
252
{
253
    return QSize(500, 500);
254
}
255

    
256
void Scene::initializeGL()
257
{
258
    // V prubehu chodu aplikace muze dojit ke zruseni sceny a k jejimu opetovnemu
259
    // vytvoreni (opetovnemu zavolani initializeGL()). Proto je vhodne po sobe
260
    // uklidit v pripade teto nastale udalosti.
261
    QObject::connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(clear()));
262
    
263
    // Vytvoreni GLSL podprogramu. Pridani zdrojovych souboru a napojeni attribute
264
    // promennych na hodnoty, ktere budou vyuzivany pri mapovani hodnot.
265
    shaderProgram = new QOpenGLShaderProgram();
266
    shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/glsl/shader.vert");
267
    shaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/glsl/shader.frag");
268
    shaderProgram->bindAttributeLocation("vertex", 0);
269
    shaderProgram->bindAttributeLocation("normal", 1);
270
    shaderProgram->bindAttributeLocation("group", 2);
271
    shaderProgram->link();
272
    
273
    shaderProgram->bind();
274
    
275
    // Vytvoreni textur a pocatecni inicializace uniform atributu TEXTURE.
276
    for (int i = 0; i < TEXTURE_COUNT; i++)
277
    {
278
        textures[i] = new QOpenGLTexture(QImage(texturePath[i]).mirrored());
279
    }
280
    shaderProgram->setUniformValue("texture", 0);
281
    
282
    // Zjisteni lokaci ostatnich uniform atributu.
283
    projectionLocation = shaderProgram->uniformLocation("un_Projection");
284
    lightLocation = shaderProgram->uniformLocation("un_Light");
285
    for (int i = 0; i < FIRST_TYPE_WALL_I; i++)
286
    {
287
        normalLocations[i] = shaderProgram->uniformLocation(QString("un_Normal[%1]").arg(i));
288
        mvLocations[i] = shaderProgram->uniformLocation(QString("un_ModelView[%1]").arg(i));
289
        
290
        // U barev rovnou nastavit i obsah promennych.
291
        int colorLocation = shaderProgram->uniformLocation(QString("un_Color[%1]").arg(i));
292
        shaderProgram->setUniformValue(colorLocation, colorValues[i]);
293
    }
294
    
295
    // Pocatecni inicializace pozice svetla a spusteni shader programu.
296
    shaderProgram->setUniformValue(lightLocation, QVector3D(0, 0, 0));
297
    shaderProgram->release();
298
    
299
    // Pro jistotu, manualni vytvoreni pole pro vrcholy a spojeni se scenou.
300
    vao.create();
301
    QOpenGLVertexArrayObject::Binder vaoBinder(&vao);
302
    
303
    // Vytvoreni buffer pro vrcholy.
304
    buffer.create();
305
    buffer.bind();
306
    
307
    // Namapovani hodnot z bufferu na attribute promenne v shaderu.
308
    QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
309
    f->glEnableVertexAttribArray(0);
310
    f->glEnableVertexAttribArray(1);
311
    f->glEnableVertexAttribArray(2);
312
    f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, Element::DATA_COUNT_FOR_VERTEX * sizeof(GLfloat), reinterpret_cast<void *>(0 * sizeof(GLfloat)));
313
    f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, Element::DATA_COUNT_FOR_VERTEX * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
314
    f->glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, Element::DATA_COUNT_FOR_VERTEX * sizeof(GLfloat), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
315
    buffer.release();
316
    
317
    // Nastaveni vykreslovacich modu.
318
    glEnable(GL_DEPTH_TEST);
319
    glEnable(GL_CULL_FACE);
320
    glEnable(GL_MULTISAMPLE); // Anti-aliasing (s QSurfaceFormat::setSamples(4)).
321
    glEnable(GL_BLEND); // Pruhlednost.
322
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
323
}
324

    
325
void Scene::paintGL()
326
{
327
    QOpenGLVertexArrayObject::Binder vaoBinder(&vao);
328
    shaderProgram->bind();
329
    
330
    // Nastaveni zmenenych globalnich promennych shaderum.
331
    shaderProgram->setUniformValue(projectionLocation, projection);
332
    for (int i = 0; i < FIRST_TYPE_WALL_I; i++)
333
    {
334
        shaderProgram->setUniformValue(normalLocations[i], worlds[i].normalMatrix());
335
        shaderProgram->setUniformValue(mvLocations[i], camera * worlds[i]);
336

    
337
        // U vsech vykreslovanych prvku nastavit globalni rotaci.
338
        worlds[i].setToIdentity();
339
        worlds[i].rotate(xAngle / (float) ROTATE_REDUCTION, QVector3D(1, 0, 0));
340
        worlds[i].rotate(yAngle / (float) ROTATE_REDUCTION, QVector3D(0, 1, 0));
341
        
342
        if (i > TRAJECTORY_I)
343
        {
344
            float sphereScaling;
345
            if (i == SPHERE_II) {
346
                worlds[i].translate(((Sphere *) (elements[SPHERE_II]))->getPosition());
347
                sphereScaling = ((Sphere *) elements[SPHERE_II])->getCurrentScaling();
348
            } else {
349
                // Jak pro kouli, tak pro sipky, provest posunuti do nastaveneho bodu.
350
                worlds[i].translate(((Sphere *) (elements[SPHERE_I]))->getPosition());
351
                sphereScaling = ((Sphere *) elements[SPHERE_I])->getCurrentScaling();
352
            }
353
            
354
            if (i == SPHERE_I)
355
            {
356
                // Pro kouli provest danou zmenu meritka.
357
                worlds[i].scale(sphereScaling);
358
            } else if (i == SPHERE_II) {
359
                worlds[i].scale(sphereScaling);
360
            } else {
361
                QVector3D top = QVector3D(0, 1, 0);
362
                
363
                QVector3D arrow;
364
                float arrowScaling;
365
                if (i == FIRST_ARROW_I)
366
                {
367
                    arrow = firstArrow;
368
                    arrowScaling = FIRST_ARROW_WIDTH_SCALING;
369
                }
370
                else
371
                {
372
                    arrow = secondArrow;
373
                    arrowScaling = SECOND_ARROW_WIDTH_SCALING;
374
                }
375
                
376
                // Pro obe sipky urcit, podle jakeho vektoru ma byt provedena
377
                // rotace, o jaky uhel maji byt orotovany a podle velikosti
378
                // vektoru nastavit i zmenu meritka.
379
                float angle = acos(QVector3D::dotProduct(arrow, top) / (arrow.length() * top.length())) * 180 / M_PI;
380
                QVector3D normal = QVector3D::crossProduct(top, arrow);
381
                worlds[i].rotate(angle, normal);
382
                worlds[i].scale(sphereScaling * arrowScaling, sphereScaling * arrow.length(), sphereScaling * arrowScaling);
383
            }
384
        }
385
    }
386
    
387
    // Nastavit kam ma byt provedeno vykreslovani a vycistit 3D scenu.
388
    glViewport(0, 0, width(), height());
389
    glClearColor(backgroundColor.x(), backgroundColor.y(), backgroundColor.z(), 1);
390
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
391
    
392
    if (((Trajectory *) elements[TRAJECTORY_I])->isSet())
393
    {
394
        // Pomocna promenna pro urceni pocatecnich indexu vykreslovacich komponent.
395
        int vertCount = 0;
396

    
397
        // Vykresleni vsech grafickych prvku az na zdi.
398
        int i;
399
        int auxVertexCount = 0;
400
        bool sphereIsSet = ((Sphere *) elements[SPHERE_I])->isSet();
401
        //bool staticSphereIsSet = ((Sphere *) elements[SPHERE_II])->isSet();
402
        for (i = 0; i < FIRST_TYPE_WALL_I; i++)
403
        {
404
            vertCount += elements[i]->vertexCount();
405
            if (!sphereIsSet && i > 0)
406
            {
407
                auxVertexCount += elements[i]->vertexCount();
408
            }
409
        }
410
        // Pokud neni nastavena pozice pro kouli a sipky, vykreslit pouze trajektorii.
411
        glDrawArrays(GL_TRIANGLES, 0, vertCount - auxVertexCount);
412

    
413
        // Vykresleni zdi, stropu a podlah.
414
        for (int j = 0; j < TEXTURE_COUNT; j++, i++)
415
        {
416
            textures[j]->bind();
417
            glDrawArrays(GL_QUADS, vertCount, elements[i]->vertexCount());
418
            vertCount += elements[i]->vertexCount();
419
        }
420
    }
421

    
422
    shaderProgram->release();
423
    buffer.release();
424
}
425

    
426
void Scene::resizeGL(int w, int h)
427
{
428
    // Nastavit matici projekce pri kazde zmene velikosti okna.
429
    projection.setToIdentity();
430
    projection.perspective(eyeAngle, w / (float) h, 1, 40000);
431
}
432

    
433
void Scene::mousePressEvent(QMouseEvent *event)
434
{
435
    // Pri kazdem stisknuti tlacitka ulozit, kde je kurzor (kvuli otaceni).
436
    lastPosition = event->pos();
437
}
438

    
439
void Scene::mouseMoveEvent(QMouseEvent *event)
440
{
441
    if (event->buttons() == Qt::LeftButton || event->buttons() == Qt::RightButton)
442
    {
443
        // Pro obe tlacitka otacet stejne, konkretne podle osy X a Y.
444
        int dx = event->x() - lastPosition.x();
445
        int dy = event->y() - lastPosition.y();
446
        lastPosition = event->pos();
447
        setXAngle(xAngle + 5 * dy);
448
        setYAngle(yAngle + 5 * dx);
449
        update();
450
    }
451
}
452

    
453
void Scene::wheelEvent(QWheelEvent *e)
454
{
455
    // Pri pohybu kolecka na mysi priblizovat ci oddalovat scenu (resp. kameru
456
    // k/od pocatku soustavy souradnic).
457
    if (e != NULL)
458
    {
459
        if (e->delta() > 0)
460
        {
461
            camera.zoomOut();
462
        }
463
        else
464
        {
465
            camera.zoomIn();
466
        }
467
    }
468
}
469

    
470
void Scene::updateBufferData()
471
{
472
    int resultDataCount = 0;
473
    for (int i = 0; i < ELEMENT_COUNT; i++)
474
    {
475
        resultDataCount += elements[i]->dataCount();
476
    }
477
    
478
    // Vytvoreni pole s hodnotami pro vsechny vykreslovane prvky.
479
    GLfloat *resultData = new GLfloat[resultDataCount];
480
    int resultDataIndex = 0;
481
    for (int i = 0; i < ELEMENT_COUNT; i++)
482
    {
483
        const GLfloat *data = elements[i]->getData();
484
        for (int j = 0; j < elements[i]->dataCount(); j++)
485
        {
486
            resultData[resultDataIndex++] = data[j];
487
        }
488
    }
489
    
490
    // Prenastavit obsah bufferu.
491
    buffer.bind();
492
    buffer.allocate(resultData, resultDataCount * sizeof(GLfloat));
493
    delete[] resultData;
494
}
495

    
496
void Scene::setXAngle(int angle)
497
{
498
    angle %= 360 * ROTATE_REDUCTION;
499
    
500
    if (angle != xAngle)
501
    {
502
        xAngle = angle;
503
    }
504
}
505

    
506
void Scene::setYAngle(int angle)
507
{
508
    angle %= 360 * ROTATE_REDUCTION;
509
    
510
    if (angle != yAngle)
511
    {
512
        yAngle = angle;
513
    }
514
}
515

    
516
void Scene::clear()
517
{
518
    if (shaderProgram != NULL)
519
    {
520
        makeCurrent();
521
        
522
        // Zruseni vytvoreneho bufferu pro data pro vrcholy.
523
        // Uvolneni pameti od alokovaneho pole pro vsechny hodnoty vsech vrcholu
524
        // viz updateBufferData().
525
        buffer.destroy();
526
        
527
        // Zruseni GLSL podprogramu.
528
        delete shaderProgram;
529
        shaderProgram = NULL;
530
        
531
        // Vycisteni pameti od alokovanych textur.
532
        for (int i = 0; i < TEXTURE_COUNT; i++)
533
        {
534
            textures[i]->destroy();
535
            textures[i] = NULL;
536
        }
537
        
538
        doneCurrent();
539
    }
540
}
(3-3/4)