Selaa lähdekoodia

Rewrote Sprite loading in Game

Thomas Buck 11 vuotta sitten
vanhempi
commit
c3f431e6ef
7 muutettua tiedostoa jossa 1315 lisäystä ja 1488 poistoa
  1. 4
    0
      ChangeLog.md
  2. 20
    0
      include/Room.h
  3. 1
    2
      include/Sprite.h
  4. 8
    38
      include/World.h
  5. 1210
    1232
      src/Game.cpp
  6. 1
    2
      src/Sprite.cpp
  7. 71
    214
      src/World.cpp

+ 4
- 0
ChangeLog.md Näytä tiedosto

2
 
2
 
3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
4
 
4
 
5
+    [ 20140504 ]
6
+    * Forcing use of new Room and Sprite classes in World.
7
+    * Rewrote Sprite loading code in Game
8
+
5
     [ 20140503 ]
9
     [ 20140503 ]
6
     * Started big World-Data refactoring.
10
     * Started big World-Data refactoring.
7
       - Created Sprite class with drawing code from Render
11
       - Created Sprite class with drawing code from Render

+ 20
- 0
include/Room.h Näytä tiedosto

30
 public:
30
 public:
31
     Portal(vec3_t _vertices[4], vec3_t _normal, int _adjoiningRoom);
31
     Portal(vec3_t _vertices[4], vec3_t _normal, int _adjoiningRoom);
32
 
32
 
33
+    vec3_t *getVertices();
34
+    int getAdjoiningRoom();
35
+
33
 private:
36
 private:
34
     vec3_t vertices[4];
37
     vec3_t vertices[4];
35
     vec3_t normal;
38
     vec3_t normal;
50
 class Sector {
53
 class Sector {
51
 public:
54
 public:
52
     Sector(vec_t _floor, vec_t _ceiling, bool _wall);
55
     Sector(vec_t _floor, vec_t _ceiling, bool _wall);
56
+    vec_t getFloor();
57
+    vec_t getCeiling();
58
+    bool isWall();
53
 
59
 
54
 private:
60
 private:
55
     vec_t floor;
61
     vec_t floor;
66
     Room(int _id);
72
     Room(int _id);
67
     ~Room();
73
     ~Room();
68
 
74
 
75
+    unsigned int getFlags();
76
+    unsigned int getNumXSectors();
77
+    unsigned int getNumZSectors();
78
+    void getPos(vec_t *target);
79
+
80
+    bool inBox(vec_t x, vec_t y, vec_t z);
81
+    bool inBoxPlane(vec_t x, vec_t z);
82
+
83
+    unsigned int sizePortals();
84
+    Portal &getPortal(unsigned int index);
85
+
86
+    unsigned int sizeSectors();
87
+    Sector &getSector(unsigned int index);
88
+
69
 private:
89
 private:
70
     int id;
90
     int id;
71
     unsigned int flags;
91
     unsigned int flags;

+ 1
- 2
include/Sprite.h Näytä tiedosto

12
 
12
 
13
 class Sprite {
13
 class Sprite {
14
 public:
14
 public:
15
-    Sprite(int _numVerts, vec3_t _vertex[4], vec2_t _texel[4], vec3_t _pos, vec_t _radius, int _texture);
15
+    Sprite(vec3_t _vertex[4], vec2_t _texel[4], vec3_t _pos, vec_t _radius, int _texture);
16
     void display();
16
     void display();
17
 
17
 
18
 private:
18
 private:
19
-    int numVerts;     //!< 4 == Quad, 3 == Triangle, rendered as triangles
20
     vec3_t vertex[4];
19
     vec3_t vertex[4];
21
     vec2_t texel[4];
20
     vec2_t texel[4];
22
     vec3_t pos;
21
     vec3_t pos;

+ 8
- 38
include/World.h Näytä tiedosto

12
 #include <list>
12
 #include <list>
13
 #include <vector>
13
 #include <vector>
14
 
14
 
15
-#define BAD_BLOOD //!< \todo For temp rendering use
16
-
17
-#ifdef BAD_BLOOD
18
-#include "SkeletalModel.h"
19
-#else
20
 #include "Room.h"
15
 #include "Room.h"
21
 #include "Sprite.h"
16
 #include "Sprite.h"
22
-#endif
23
 
17
 
24
 #include "WorldData.h"
18
 #include "WorldData.h"
25
 
19
 
34
      */
28
      */
35
     ~World();
29
     ~World();
36
 
30
 
37
-#ifdef BAD_BLOOD
38
-
39
-    //! \todo Temp methods for rendering use until more refactoring is done
40
-
41
-    /*!
42
-     * \brief Adds room to world
43
-     * \param room room to add
44
-     */
45
-    void addRoom(room_mesh_t *room);
46
-
47
     /*!
31
     /*!
48
      * \brief Adds mesh to world
32
      * \brief Adds mesh to world
49
      * \param model mesh to add
33
      * \param model mesh to add
64
     int addModel(skeletal_model_t *model);
48
     int addModel(skeletal_model_t *model);
65
 
49
 
66
     /*!
50
     /*!
67
-     * \brief Adds sprite to world
68
-     * \param sprite sprite to add
69
-     */
70
-    void addSprite(sprite_seq_t *sprite);
71
-
72
-    /*!
73
      * \brief Move entity in given direction unless collision occurs
51
      * \brief Move entity in given direction unless collision occurs
74
      * \param e entity to move
52
      * \param e entity to move
75
      * \param movement direction of movement ('f', 'b', 'l' or 'r')
53
      * \param movement direction of movement ('f', 'b', 'l' or 'r')
78
 
56
 
79
     model_mesh_t *getMesh(int index);
57
     model_mesh_t *getMesh(int index);
80
     skeletal_model_t *getModel(int index);
58
     skeletal_model_t *getModel(int index);
81
-    room_mesh_t *getRoom(int index);
82
     std::vector<entity_t *> *getEntities();
59
     std::vector<entity_t *> *getEntities();
83
-    std::vector<sprite_seq_t *> *getSprites();
84
-    std::vector<room_mesh_t *> *getRooms();
85
-
86
-#else
87
 
60
 
88
     void addRoom(Room &room);
61
     void addRoom(Room &room);
89
 
62
 
63
+    unsigned int sizeRoom();
64
+
65
+    Room &getRoom(unsigned int index);
66
+
90
     void addSprite(SpriteSequence &sprite);
67
     void addSprite(SpriteSequence &sprite);
91
 
68
 
92
-#endif
69
+    unsigned int sizeSprite();
70
+
71
+    SpriteSequence &getSprite(unsigned int index);
93
 
72
 
94
     /*!
73
     /*!
95
      * \brief Find room a location is in.
74
      * \brief Find room a location is in.
156
      * \param x X coordinate
135
      * \param x X coordinate
157
      * \param y will be set to world height in that room
136
      * \param y will be set to world height in that room
158
      * \param z Z coordinate
137
      * \param z Z coordinate
159
-     * \returns true if position is in a room
160
      */
138
      */
161
-    bool getHeightAtPosition(int index, float x, float *y, float z);
139
+    void getHeightAtPosition(int index, float x, float *y, float z);
162
 
140
 
163
     /*!
141
     /*!
164
      * \brief Clears all data in world
142
      * \brief Clears all data in world
168
 
146
 
169
 private:
147
 private:
170
 
148
 
171
-#ifdef BAD_BLOOD
172
-
173
     // Old World
149
     // Old World
174
     std::vector<entity_t *> mEntities;       //!< World entities
150
     std::vector<entity_t *> mEntities;       //!< World entities
175
-    std::vector<room_mesh_t *> mRooms;       //!< Map data and meshes
176
     std::vector<model_mesh_t *> mMeshes;     //!< Unanimated meshes
151
     std::vector<model_mesh_t *> mMeshes;     //!< Unanimated meshes
177
-    std::vector<sprite_seq_t *> mSprites;    //!< Sprites
178
     std::vector<skeletal_model_t *> mModels; //!< Skeletal animation models
152
     std::vector<skeletal_model_t *> mModels; //!< Skeletal animation models
179
 
153
 
180
-#else
181
-
182
     // New World
154
     // New World
183
     std::vector<Room *> mRooms;
155
     std::vector<Room *> mRooms;
184
     std::vector<SpriteSequence *> mSprites;
156
     std::vector<SpriteSequence *> mSprites;
185
 
157
 
186
-#endif
187
-
188
 };
158
 };
189
 
159
 
190
 #endif
160
 #endif

+ 1210
- 1232
src/Game.cpp
File diff suppressed because it is too large
Näytä tiedosto


+ 1
- 2
src/Sprite.cpp Näytä tiedosto

33
     return *sprites.at(index);
33
     return *sprites.at(index);
34
 }
34
 }
35
 
35
 
36
-Sprite::Sprite(int _numVerts, vec3_t _vertex[4], vec2_t _texel[4], vec3_t _pos, vec_t _radius, int _texture) {
36
+Sprite::Sprite(vec3_t _vertex[4], vec2_t _texel[4], vec3_t _pos, vec_t _radius, int _texture) {
37
-    numVerts = _numVerts;
38
     radius = _radius;
37
     radius = _radius;
39
     texture = _texture;
38
     texture = _texture;
40
     for (unsigned int i = 0; i < 3; i++) {
39
     for (unsigned int i = 0; i < 3; i++) {

+ 71
- 214
src/World.cpp Näytä tiedosto

18
 
18
 
19
 
19
 
20
 // Temp methods for rendering use until more refactoring is done
20
 // Temp methods for rendering use until more refactoring is done
21
-#ifdef BAD_BLOOD
22
 model_mesh_t *World::getMesh(int index)
21
 model_mesh_t *World::getMesh(int index)
23
 {
22
 {
24
     return mMeshes[index];
23
     return mMeshes[index];
29
     return mModels[index];
28
     return mModels[index];
30
 }
29
 }
31
 
30
 
32
-room_mesh_t *World::getRoom(int index)
33
-{
34
-    return mRooms[index];
35
-}
36
-
37
 std::vector<entity_t *> *World::getEntities()
31
 std::vector<entity_t *> *World::getEntities()
38
 {
32
 {
39
     return &mEntities;
33
     return &mEntities;
40
 }
34
 }
41
 
35
 
42
-std::vector<sprite_seq_t *> *World::getSprites()
43
-{
44
-    return &mSprites;
45
-}
46
-
47
-std::vector<room_mesh_t *> *World::getRooms()
48
-{
49
-    return &mRooms;
50
-}
51
-
52
-void World::addRoom(room_mesh_t *room)
53
-{
54
-    mRooms.push_back(room);
55
-}
56
-
57
-
58
 void World::addMesh(model_mesh_t *mesh)
36
 void World::addMesh(model_mesh_t *mesh)
59
 {
37
 {
60
     if (mesh)
38
     if (mesh)
86
 }
64
 }
87
 
65
 
88
 
66
 
89
-void World::addSprite(sprite_seq_t *sprite)
90
-{
91
-    if (sprite)
92
-        mSprites.push_back(sprite);
93
-}
94
-
95
-
96
 void World::moveEntity(entity_t *e, char movement)
67
 void World::moveEntity(entity_t *e, char movement)
97
 {
68
 {
98
     const float moved = 180.0f;
69
     const float moved = 180.0f;
271
     e->moving = true;
242
     e->moving = true;
272
 }
243
 }
273
 
244
 
274
-#else
275
 
245
 
276
 void World::addRoom(Room &room) {
246
 void World::addRoom(Room &room) {
277
     mRooms.push_back(&room);
247
     mRooms.push_back(&room);
278
 }
248
 }
279
 
249
 
250
+unsigned int World::sizeRoom() {
251
+    return mRooms.size();
252
+}
253
+
254
+Room &World::getRoom(unsigned int index) {
255
+    assert(index < mRooms.size());
256
+    return *mRooms.at(index);
257
+}
258
+
280
 void World::addSprite(SpriteSequence &sprite) {
259
 void World::addSprite(SpriteSequence &sprite) {
281
     mSprites.push_back(&sprite);
260
     mSprites.push_back(&sprite);
282
 }
261
 }
283
 
262
 
284
-#endif
263
+unsigned int World::sizeSprite() {
264
+    return mSprites.size();
265
+}
266
+
267
+SpriteSequence &World::getSprite(unsigned int index) {
268
+    assert(index < mSprites.size());
269
+    return *mSprites.at(index);
270
+}
285
 
271
 
286
 
272
 
287
 int World::getRoomByLocation(int index, float x, float y, float z)
273
 int World::getRoomByLocation(int index, float x, float y, float z)
288
 {
274
 {
289
-    room_mesh_t *room = mRooms[index];
275
+    assert(index >= 0);
290
-
276
+    assert(index < mRooms.size());
291
-    if (room)
277
+    Room &room = *mRooms.at(index);
292
-    {
293
-        if (x > room->bbox_min[0] && x < room->bbox_max[0] &&
294
-                z > room->bbox_min[2] && z < room->bbox_max[2])
295
-        {
296
-            if (y > room->bbox_min[1] && y < room->bbox_max[1])
297
-                return index;
298
-        }
299
-    }
300
 
278
 
301
-    return getRoomByLocation(x, y, z);
279
+    if (room.inBox(x, y, z))
280
+        return index;
281
+    else
282
+        return getRoomByLocation(x, y, z);
302
 }
283
 }
303
 
284
 
304
 
285
 
305
-int World::getRoomByLocation(float x, float y, float z)
286
+int World::getRoomByLocation(float x, float y, float z) {
306
-{
307
-    room_mesh_t *room;
308
     int hop = -1;
287
     int hop = -1;
309
 
288
 
310
-
289
+    for (unsigned int i = 0; i < mRooms.size(); i++) {
311
-    for(std::vector<int>::size_type i = 0; i < mRooms.size(); i++)
290
+        if (mRooms.at(i)->inBoxPlane(x, z)) {
312
-    {
291
+            if (mRooms.at(i)->inBox(x, y, z))
313
-        room = mRooms[i];
314
-
315
-        if (!room)
316
-            continue;
317
-
318
-        if ((x > room->bbox_min[0]) && (x < room->bbox_max[0]) &&
319
-                (z > room->bbox_min[2]) && (z < room->bbox_max[2]))
320
-        {
321
-            // This room contains current position
322
-            if ((y > room->bbox_min[1]) && (y < room->bbox_max[1]))
323
                 return i;
292
                 return i;
324
-
293
+            else
325
-            // This room is above or below current position
294
+                hop = i; // This room is above or below current position
326
-            hop = i;
327
         }
295
         }
328
     }
296
     }
329
 
297
 
330
-    // Room is -1?  Must be in void, try to hop to room with same X,Z
331
     return hop;
298
     return hop;
332
-    //return -1;
333
 }
299
 }
334
 
300
 
335
 
301
 
336
 int World::getAdjoiningRoom(int index,
302
 int World::getAdjoiningRoom(int index,
337
         float x, float y, float z,
303
         float x, float y, float z,
338
-        float x2, float y2, float z2)
304
+        float x2, float y2, float z2) {
339
-{
305
+    assert(index >= 0);
340
-    room_mesh_t *room = mRooms[index];
306
+    assert(index < mRooms.size());
341
-    portal_t * portal;
307
+    Room &room = *mRooms.at(index);
342
     vec3_t intersect, p1, p2;
308
     vec3_t intersect, p1, p2;
343
 
309
 
344
-
345
     p1[0] = x;  p1[1] = y;  p1[2] = z;
310
     p1[0] = x;  p1[1] = y;  p1[2] = z;
346
     p2[0] = x2; p2[1] = y2; p2[2] = z2;
311
     p2[0] = x2; p2[1] = y2; p2[2] = z2;
347
 
312
 
348
-    if (room)
313
+    for (unsigned int i = 0; i < room.sizePortals(); i++) {
349
-    {
314
+        if (intersectionLinePolygon(intersect, p1, p2, //4,
350
-        for(std::vector<int>::size_type i = 0; i != room->portals.size(); i++)
315
+                    room.getPortal(i).getVertices()))
351
-        {
316
+            return room.getPortal(i).getAdjoiningRoom();
352
-            portal = room->portals[i];
353
-
354
-            if (!portal)
355
-                continue;
356
-
357
-            if (intersectionLinePolygon(intersect, p1, p2, // 4,
358
-                        portal->vertices))
359
-            {
360
-                return portal->adjoining_room;
361
-            }
362
-        }
363
     }
317
     }
364
 
318
 
365
     return -1;
319
     return -1;
366
 }
320
 }
367
 
321
 
368
 
322
 
369
-int World::getSector(int room, float x, float z, float *floor, float *ceiling)
323
+int World::getSector(int room, float x, float z, float *floor, float *ceiling) {
370
-{
371
-    room_mesh_t *r;
372
-    sector_t * s;
373
-    int sector;
374
-
375
     assert(room >= 0);
324
     assert(room >= 0);
325
+    assert(room < mRooms.size());
376
     assert(floor != NULL);
326
     assert(floor != NULL);
377
     assert(ceiling != NULL);
327
     assert(ceiling != NULL);
378
 
328
 
379
-    r = mRooms[room];
329
+    int sector = getSector(room, x, z);
380
-
381
-    if (!r)
382
-        return -1;
383
-
384
-    sector = (((((int)x - (int)r->pos[0]) / 1024) * r->numZSectors) +
385
-            (((int)z - (int)r->pos[2]) / 1024));
386
-
387
-    if (sector > -1)
388
-    {
389
-        s = r->sectors[sector];
390
 
330
 
391
-        if (!s)
331
+    if ((sector >= 0) && (sector < mRooms.at(room)->sizeSectors())) {
392
-            return -1;
332
+        *floor = mRooms.at(room)->getSector(sector).getFloor();
393
-
333
+        *ceiling = mRooms.at(room)->getSector(sector).getCeiling();
394
-        *floor = s->floor;
395
-        *ceiling = s->ceiling;
396
     }
334
     }
397
 
335
 
398
     return sector;
336
     return sector;
400
 
338
 
401
 
339
 
402
 int World::getSector(int room, float x, float z) {
340
 int World::getSector(int room, float x, float z) {
403
-    int sector;
341
+    assert(room >= 0);
404
-    room_mesh_t *r;
342
+    assert(room < mRooms.size());
405
-
406
-    if ((room < 0) || (room >= (int)mRooms.size()))
407
-        return -1;
408
-
409
-    r = mRooms[room];
410
-
411
-    if (!r)
412
-        return -1;
413
 
343
 
414
-    sector = (((((int)x - (int)r->pos[0]) / 1024) * r->numZSectors) +
344
+    vec3_t pos;
415
-            (((int)z - (int)r->pos[2]) / 1024));
345
+    mRooms.at(room)->getPos(pos);
346
+    int sector = (((((int)x - (int)pos[0]) / 1024) *
347
+        mRooms.at(room)->getNumZSectors()) + (((int)z - (int)pos[2]) / 1024));
416
 
348
 
417
     if (sector < 0)
349
     if (sector < 0)
418
         return -1;
350
         return -1;
422
 
354
 
423
 
355
 
424
 unsigned int World::getRoomInfo(int room) {
356
 unsigned int World::getRoomInfo(int room) {
425
-    room_mesh_t *r;
357
+    assert(room >= 0);
426
-
358
+    assert(room < mRooms.size());
427
-    if ((room >= (int)mRooms.size()) || (room < 0))
428
-        return 0;
429
-
430
-    r = mRooms[room];
431
-
432
-    if (!r)
433
-        return 0;
434
 
359
 
435
-    return r->flags;
360
+    return mRooms.at(room)->getFlags();
436
 }
361
 }
437
 
362
 
438
 
363
 
439
 bool World::isWall(int room, int sector) {
364
 bool World::isWall(int room, int sector) {
440
-    room_mesh_t *r;
365
+    assert(room >= 0);
441
-    sector_t *sect;
366
+    assert(room < mRooms.size());
442
-
367
+    assert(sector >= 0);
443
-    if ((room >= (int)mRooms.size()) || (room < 0))
368
+    assert(sector < mRooms.at(room)->sizeSectors());
444
-        return true;
445
-
446
-    r = mRooms[room];
447
-
448
-    if ((!r) || (sector >= (int)r->sectors.size()) || (sector < 0))
449
-        return true;
450
-
451
-    sect = r->sectors[sector];
452
-
453
-    if (!sect)
454
-        return true;
455
 
369
 
456
-    return ((sector > 0) && sect->wall); //! \fixme is (sector > 0) correct??
370
+    //! \fixme is (sector > 0) correct??
371
+    return ((sector > 0) && mRooms.at(room)->getSector(sector).isWall());
457
 }
372
 }
458
 
373
 
459
 
374
 
460
-bool World::getHeightAtPosition(int index, float x, float *y, float z)
375
+void World::getHeightAtPosition(int index, float x, float *y, float z) {
461
-{
376
+    assert(index >= 0);
462
-    room_mesh_t *room = mRooms[index];
377
+    assert(index < mRooms.size());
463
-    int sector;
464
-    sector_t *sect;
465
-
466
-    if (!room)
467
-    {
468
-        return false;
469
-    }
470
-
471
-    // Mongoose 2002.08.14, Remember sector_z is width of sector array
472
-    sector = getSector(index, x, z);
473
-
474
-    sect = room->sectors[sector];
475
 
378
 
476
-    if (!sect)
379
+    int sector = getSector(index, x, z);
477
-    {
380
+    if ((sector >= 0) && (sector < mRooms.at(index)->sizeSectors()))
478
-        return true;
381
+        *y = mRooms.at(index)->getSector(sector).getFloor();
479
-    }
480
-
481
-    *y = sect->floor;
482
-
483
-    return true;
484
 }
382
 }
485
 
383
 
486
 
384
 
487
 void World::destroy()
385
 void World::destroy()
488
 {
386
 {
489
-    room_mesh_t *room;
387
+    for (unsigned int i = 0; i != mRooms.size(); i++)
388
+        delete mRooms[i];
389
+
390
+    for (unsigned int i = 0; i != mSprites.size(); i++)
391
+        delete mSprites[i];
392
+
490
     model_mesh_t *mesh;
393
     model_mesh_t *mesh;
491
-    sprite_seq_t *sprite;
492
     skeletal_model_t *model;
394
     skeletal_model_t *model;
493
     bone_frame_t *boneframe;
395
     bone_frame_t *boneframe;
494
     bone_tag_t *tag;
396
     bone_tag_t *tag;
497
 
399
 
498
     for (std::vector<int>::size_type i = 0; i != mEntities.size(); i++)
400
     for (std::vector<int>::size_type i = 0; i != mEntities.size(); i++)
499
         delete mEntities[i];
401
         delete mEntities[i];
500
-    mEntities.clear();
501
-
502
-    for (std::vector<int>::size_type i = 0; i != mRooms.size(); i++) {
503
-        room = mRooms[i];
504
-
505
-        if (room) {
506
-            //! \fixme Causes "freeing already freed pointer" exceptions or EXEC_BAD_ACCESS
507
-
508
-            //for (std::vector<int>::size_type j = 0; j != room->portals.size(); j++)
509
-            //    delete room->portals[i];
510
-            room->portals.clear();
511
-
512
-            //for (std::vector<int>::size_type j = 0; j != room->models.size(); j++)
513
-            //    delete room->models[i];
514
-            room->models.clear();
515
-
516
-            //for (std::vector<int>::size_type j = 0; j != room->sprites.size(); j++)
517
-            //    delete room->sprites[i];
518
-            room->sprites.clear();
519
-
520
-            //for (std::vector<int>::size_type j = 0; j != room->sectors.size(); j++)
521
-            //    delete room->sectors[i];
522
-            room->sectors.clear();
523
-
524
-            //for (std::vector<int>::size_type j = 0; j != room->boxes.size(); j++)
525
-            //    delete room->boxes[i];
526
-            room->boxes.clear();
527
-
528
-            delete room;
529
-        }
530
-    }
531
 
402
 
532
     for (std::vector<int>::size_type i = 0; i != mMeshes.size(); i++) {
403
     for (std::vector<int>::size_type i = 0; i != mMeshes.size(); i++) {
533
         mesh = mMeshes[i];
404
         mesh = mMeshes[i];
569
 
440
 
570
     mMeshes.clear();
441
     mMeshes.clear();
571
 
442
 
572
-    for (std::vector<int>::size_type i = 0; i != mSprites.size(); i++) {
573
-        sprite = mSprites[i];
574
-
575
-        if (!sprite)
576
-            continue;
577
-
578
-        if (sprite->sprite)
579
-            delete [] sprite->sprite;
580
-
581
-        delete sprite;
582
-    }
583
-
584
-    mSprites.clear();
585
-
586
     for (std::vector<int>::size_type i = 0; i != mModels.size(); i++) {
443
     for (std::vector<int>::size_type i = 0; i != mModels.size(); i++) {
587
         model = mModels[i];
444
         model = mModels[i];
588
 
445
 

Loading…
Peruuta
Tallenna