Browse Source

LoaderTR2 loads Moveables and Entities

Thomas Buck 10 years ago
parent
commit
00706b69ab
11 changed files with 312 additions and 29 deletions
  1. 3
    0
      ChangeLog.md
  2. 2
    0
      include/Entity.h
  3. 1
    0
      include/Game.h
  4. 11
    0
      include/SkeletalModel.h
  5. 2
    2
      src/Console.cpp
  6. 15
    0
      src/Entity.cpp
  7. 14
    1
      src/Game.cpp
  8. 40
    0
      src/SkeletalModel.cpp
  9. 3
    3
      src/TextureManager.cpp
  10. 4
    4
      src/commands/Command.cpp
  11. 217
    19
      src/loader/LoaderTR2.cpp

+ 3
- 0
ChangeLog.md View File

2
 
2
 
3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
4
 
4
 
5
+    [ 20141206 ]
6
+    * LoaderTR2 now tries to load Moveables and Entities
7
+
5
     [ 20141203 ]
8
     [ 20141203 ]
6
     * Renamed Vector3d to Vec3, small cleanup
9
     * Renamed Vector3d to Vec3, small cleanup
7
     * Added preliminary math unit test
10
     * Added preliminary math unit test

+ 2
- 0
include/Entity.h View File

21
         MoveTypeSwim       = 3
21
         MoveTypeSwim       = 3
22
     } MoveType;
22
     } MoveType;
23
 
23
 
24
+    Entity(float p[3], float a[3], int id, long r, unsigned int model);
25
+
24
     Entity(TombRaider& tr, unsigned int index, unsigned int i, unsigned int model);
26
     Entity(TombRaider& tr, unsigned int index, unsigned int i, unsigned int model);
25
 
27
 
26
     bool operator<(Entity& o);
28
     bool operator<(Entity& o);

+ 1
- 0
include/Game.h View File

33
     void handleMouseMotion(int xrel, int yrel, int xabs, int yabs);
33
     void handleMouseMotion(int xrel, int yrel, int xabs, int yabs);
34
 
34
 
35
     Entity& getLara();
35
     Entity& getLara();
36
+    void setLara(long lara);
36
 
37
 
37
   private:
38
   private:
38
 
39
 

+ 11
- 0
include/SkeletalModel.h View File

15
 
15
 
16
 class BoneTag {
16
 class BoneTag {
17
   public:
17
   public:
18
+    BoneTag(int m, float o[3], float r[3], char f);
19
+
18
     BoneTag(TombRaider& tr, unsigned int index, unsigned int j, unsigned int* l,
20
     BoneTag(TombRaider& tr, unsigned int index, unsigned int j, unsigned int* l,
19
             unsigned int frame_offset);
21
             unsigned int frame_offset);
20
     void display();
22
     void display();
32
 
34
 
33
 class BoneFrame {
35
 class BoneFrame {
34
   public:
36
   public:
37
+    BoneFrame(float p[3]);
38
+
35
     BoneFrame(TombRaider& tr, unsigned int index, unsigned int frame_offset);
39
     BoneFrame(TombRaider& tr, unsigned int index, unsigned int frame_offset);
36
     ~BoneFrame();
40
     ~BoneFrame();
37
 
41
 
39
 
43
 
40
     unsigned long size();
44
     unsigned long size();
41
     BoneTag& get(unsigned long i);
45
     BoneTag& get(unsigned long i);
46
+    void add(BoneTag* t);
42
 
47
 
43
   private:
48
   private:
44
     float pos[3];
49
     float pos[3];
47
 
52
 
48
 class AnimationFrame {
53
 class AnimationFrame {
49
   public:
54
   public:
55
+    AnimationFrame(char r);
56
+
50
     AnimationFrame(TombRaider& tr, unsigned int index, int a, unsigned int* frame_offset,
57
     AnimationFrame(TombRaider& tr, unsigned int index, int a, unsigned int* frame_offset,
51
                    int frame_step);
58
                    int frame_step);
52
     ~AnimationFrame();
59
     ~AnimationFrame();
53
 
60
 
54
     unsigned long size();
61
     unsigned long size();
55
     BoneFrame& get(unsigned long i);
62
     BoneFrame& get(unsigned long i);
63
+    void add(BoneFrame* f);
56
 
64
 
57
   private:
65
   private:
58
     char rate;
66
     char rate;
61
 
69
 
62
 class SkeletalModel {
70
 class SkeletalModel {
63
   public:
71
   public:
72
+    SkeletalModel(int i);
73
+
64
     SkeletalModel(TombRaider& tr, unsigned int index, int objectId);
74
     SkeletalModel(TombRaider& tr, unsigned int index, int objectId);
65
     ~SkeletalModel();
75
     ~SkeletalModel();
66
     void display(unsigned long aframe, unsigned long bframe);
76
     void display(unsigned long aframe, unsigned long bframe);
71
 
81
 
72
     unsigned long size();
82
     unsigned long size();
73
     AnimationFrame& get(unsigned long i);
83
     AnimationFrame& get(unsigned long i);
84
+    void add(AnimationFrame* f);
74
 
85
 
75
   private:
86
   private:
76
     int id;
87
     int id;

+ 2
- 2
src/Console.cpp View File

87
 
87
 
88
         if (ImGui::InputText("Command", buffer, bufferLength,
88
         if (ImGui::InputText("Command", buffer, bufferLength,
89
                              ImGuiInputTextFlags_EnterReturnsTrue
89
                              ImGuiInputTextFlags_EnterReturnsTrue
90
-                              | ImGuiInputTextFlags_CallbackCompletion
91
-                              | ImGuiInputTextFlags_CallbackHistory,
90
+                             | ImGuiInputTextFlags_CallbackCompletion
91
+                             | ImGuiInputTextFlags_CallbackHistory,
92
                              &Console::callback)) {
92
                              &Console::callback)) {
93
             getLog() << "> " << buffer << Log::endl;
93
             getLog() << "> " << buffer << Log::endl;
94
             if (strlen(buffer) > 0) {
94
             if (strlen(buffer) > 0) {

+ 15
- 0
src/Entity.cpp View File

15
 
15
 
16
 #include "games/TombRaider1.h"
16
 #include "games/TombRaider1.h"
17
 
17
 
18
+Entity::Entity(float p[3], float a[3], int id, long r, unsigned int model) {
19
+    for (int i = 0; i < 3; i++) {
20
+        pos[i] = p[i];
21
+        angles[i] = a[i];
22
+    }
23
+    objectId = id;
24
+    moveType = MoveTypeWalk;
25
+    room = r;
26
+    skeletalModel = model;
27
+    boneFrame = 0;
28
+    animationFrame = 0;
29
+    idleAnimation = 0;
30
+    state = 0;
31
+}
32
+
18
 Entity::Entity(TombRaider& tr, unsigned int index, unsigned int i, unsigned int model) {
33
 Entity::Entity(TombRaider& tr, unsigned int index, unsigned int i, unsigned int model) {
19
     tr2_moveable_t* moveable = tr.Moveable();
34
     tr2_moveable_t* moveable = tr.Moveable();
20
     tr2_item_t* item = tr.Item();
35
     tr2_item_t* item = tr.Item();

+ 14
- 1
src/Game.cpp View File

82
             destroy();
82
             destroy();
83
         } else {
83
         } else {
84
             SoundManager::prepareSources();
84
             SoundManager::prepareSources();
85
+
86
+            if (mLara == -1) {
87
+                getLog() << "Can't find Lara entity in level?!" << Log::endl;
88
+            } else {
89
+                //mLoaded = true;
90
+                //getRender().setMode(Render::modeVertexLight);
91
+            }
85
         }
92
         }
86
     }
93
     }
87
 
94
 
117
         if (mLara == -1) {
124
         if (mLara == -1) {
118
             //! \todo Cutscene support
125
             //! \todo Cutscene support
119
             getLog() << "Can't find Lara entity in level pak!" << Log::endl;
126
             getLog() << "Can't find Lara entity in level pak!" << Log::endl;
120
-            destroy();
127
+            //destroy();
121
             return -1;
128
             return -1;
122
         } else {
129
         } else {
123
             mLoaded = true;
130
             mLoaded = true;
182
     return getWorld().getEntity(mLara);
189
     return getWorld().getEntity(mLara);
183
 }
190
 }
184
 
191
 
192
+void Game::setLara(long lara) {
193
+    assert(lara >= 0);
194
+    assert(lara < getWorld().sizeEntity());
195
+    mLara = lara;
196
+}
197
+
185
 void Game::processSprites() {
198
 void Game::processSprites() {
186
     for (int i = 0; i < (mTombRaider.NumItems() - 1); i++) {
199
     for (int i = 0; i < (mTombRaider.NumItems() - 1); i++) {
187
         if ((mTombRaider.Engine() == TR_VERSION_1) && (mTombRaider.Item()[i].intensity1 == -1))
200
         if ((mTombRaider.Engine() == TR_VERSION_1) && (mTombRaider.Item()[i].intensity1 == -1))

+ 40
- 0
src/SkeletalModel.cpp View File

12
 #include "SkeletalModel.h"
12
 #include "SkeletalModel.h"
13
 #include "World.h"
13
 #include "World.h"
14
 
14
 
15
+BoneTag::BoneTag(int m, float o[3], float r[3], char f) {
16
+    mesh = m;
17
+    flag = f;
18
+    for (int i = 0; i < 3; i++) {
19
+        off[i] = o[i];
20
+        rot[i] = r[i];
21
+    }
22
+}
23
+
15
 BoneTag::BoneTag(TombRaider& tr, unsigned int index, unsigned int i, unsigned int* l,
24
 BoneTag::BoneTag(TombRaider& tr, unsigned int index, unsigned int i, unsigned int* l,
16
                  unsigned int frame_offset) {
25
                  unsigned int frame_offset) {
17
     tr2_moveable_t* moveable = tr.Moveable();
26
     tr2_moveable_t* moveable = tr.Moveable();
69
     return flag;
78
     return flag;
70
 }
79
 }
71
 
80
 
81
+// ----------------------------------------------------------------------------
82
+
83
+BoneFrame::BoneFrame(float p[3]) {
84
+    for (int i = 0; i < 3; i++)
85
+        pos[i] = p[i];
86
+}
87
+
72
 BoneFrame::BoneFrame(TombRaider& tr, unsigned int index, unsigned int frame_offset) {
88
 BoneFrame::BoneFrame(TombRaider& tr, unsigned int index, unsigned int frame_offset) {
73
     tr2_moveable_t* moveable = tr.Moveable();
89
     tr2_moveable_t* moveable = tr.Moveable();
74
     unsigned short* frame = tr.Frame();
90
     unsigned short* frame = tr.Frame();
97
     return *tag.at(i);
113
     return *tag.at(i);
98
 }
114
 }
99
 
115
 
116
+void BoneFrame::add(BoneTag* t) {
117
+    tag.push_back(t);
118
+}
119
+
100
 void BoneFrame::getPosition(float p[3]) {
120
 void BoneFrame::getPosition(float p[3]) {
101
     p[0] = pos[0];
121
     p[0] = pos[0];
102
     p[1] = pos[1];
122
     p[1] = pos[1];
103
     p[2] = pos[2];
123
     p[2] = pos[2];
104
 }
124
 }
105
 
125
 
126
+// ----------------------------------------------------------------------------
127
+
128
+AnimationFrame::AnimationFrame(char r) {
129
+    rate = r;
130
+}
131
+
106
 AnimationFrame::AnimationFrame(TombRaider& tr, unsigned int index, int a,
132
 AnimationFrame::AnimationFrame(TombRaider& tr, unsigned int index, int a,
107
                                unsigned int* frame_offset, int frame_step) {
133
                                unsigned int* frame_offset, int frame_step) {
108
     tr2_moveable_t* moveable = tr.Moveable();
134
     tr2_moveable_t* moveable = tr.Moveable();
163
     return *frame.at(i);
189
     return *frame.at(i);
164
 }
190
 }
165
 
191
 
192
+void AnimationFrame::add(BoneFrame* f) {
193
+    frame.push_back(f);
194
+}
195
+
196
+// ----------------------------------------------------------------------------
197
+
198
+SkeletalModel::SkeletalModel(int i) {
199
+    id = i;
200
+}
201
+
166
 SkeletalModel::SkeletalModel(TombRaider& tr, unsigned int index, int objectId) {
202
 SkeletalModel::SkeletalModel(TombRaider& tr, unsigned int index, int objectId) {
167
     tr2_moveable_t* moveable = tr.Moveable();
203
     tr2_moveable_t* moveable = tr.Moveable();
168
     tr2_animation_t* anim = tr.Animation();
204
     tr2_animation_t* anim = tr.Animation();
394
     return *animation.at(i);
430
     return *animation.at(i);
395
 }
431
 }
396
 
432
 
433
+void SkeletalModel::add(AnimationFrame* f) {
434
+    animation.push_back(f);
435
+}
436
+

+ 3
- 3
src/TextureManager.cpp View File

47
         return true;
47
         return true;
48
 
48
 
49
     return ((vertices.at(3)->xPixel == 0)
49
     return ((vertices.at(3)->xPixel == 0)
50
-            & (vertices.at(3)->xCoordinate == 0)
51
-            & (vertices.at(3)->yPixel == 0)
52
-            & (vertices.at(3)->yCoordinate == 0));
50
+            && (vertices.at(3)->xCoordinate == 0)
51
+            && (vertices.at(3)->yPixel == 0)
52
+            && (vertices.at(3)->yCoordinate == 0));
53
 }
53
 }
54
 
54
 
55
 void TextureTile::display(float x, float y, float w, float h, float z) {
55
 void TextureTile::display(float x, float y, float w, float h, float z) {

+ 4
- 4
src/commands/Command.cpp View File

138
 
138
 
139
     std::string help("help");
139
     std::string help("help");
140
     if (begin.size() <= help.size()) {
140
     if (begin.size() <= help.size()) {
141
-                if (begin.compare(0, begin.size(), help, 0, begin.size()) == 0) {
142
-                    candidates.push_back(help);
143
-                }
144
-            }
141
+        if (begin.compare(0, begin.size(), help, 0, begin.size()) == 0) {
142
+            candidates.push_back(help);
143
+        }
144
+    }
145
 
145
 
146
     for (auto& x : commands) {
146
     for (auto& x : commands) {
147
         if (x) {
147
         if (x) {

+ 217
- 19
src/loader/LoaderTR2.cpp View File

10
 #include <vector>
10
 #include <vector>
11
 
11
 
12
 #include "global.h"
12
 #include "global.h"
13
+#include "Game.h"
13
 #include "Log.h"
14
 #include "Log.h"
14
 #include "Mesh.h"
15
 #include "Mesh.h"
15
 #include "Room.h"
16
 #include "Room.h"
75
     for (auto& x : palette)
76
     for (auto& x : palette)
76
         x = file.readU32();
77
         x = file.readU32();
77
 
78
 
78
-    // TODO store palette somewhere
79
+    // TODO store palette somewhere?
79
 
80
 
80
     uint32_t numTextiles = file.readU32();
81
     uint32_t numTextiles = file.readU32();
81
 
82
 
95
         assert(r >= 0); //! \fixme properly handle error when texture could not be loaded!
96
         assert(r >= 0); //! \fixme properly handle error when texture could not be loaded!
96
         delete [] img;
97
         delete [] img;
97
     }
98
     }
99
+
100
+    if (numTextiles > 0)
101
+        getLog() << "LoaderTR2: Found " << numTextiles << " Textures!" << Log::endl;
102
+    else
103
+        getLog() << "LoaderTR2: No Textures in this level?!" << Log::endl;
98
 }
104
 }
99
 
105
 
100
 void LoaderTR2::loadTextures() {
106
 void LoaderTR2::loadTextures() {
124
             uint8_t yCoordinate = file.readU8();
130
             uint8_t yCoordinate = file.readU8();
125
             uint8_t yPixel = file.readU8();
131
             uint8_t yPixel = file.readU8();
126
 
132
 
127
-            assert((xCoordinate != 1) || (xCoordinate != 255));
128
-            assert((yCoordinate != 1) || (yCoordinate != 255));
133
+            assert((xCoordinate == 1) || (xCoordinate == 255) || (xCoordinate == 0));
134
+            assert((yCoordinate == 1) || (yCoordinate == 255) || (yCoordinate == 0));
129
 
135
 
130
             t->add(new TextureTileVertex(xCoordinate, xPixel, yCoordinate, yPixel));
136
             t->add(new TextureTileVertex(xCoordinate, xPixel, yCoordinate, yPixel));
131
         }
137
         }
132
 
138
 
133
         getTextureManager().addTile(t);
139
         getTextureManager().addTile(t);
134
     }
140
     }
141
+
142
+    if (numObjectTextures > 0)
143
+        getLog() << "LoaderTR2: Found " << numObjectTextures << " Textiles!" << Log::endl;
144
+    else
145
+        getLog() << "LoaderTR2: No Textiles in this level?!" << Log::endl;
135
 }
146
 }
136
 
147
 
137
 void LoaderTR2::loadAnimatedTextures() {
148
 void LoaderTR2::loadAnimatedTextures() {
158
         pos += count + 1;
169
         pos += count + 1;
159
     }
170
     }
160
 
171
 
172
+    if ((numAnimatedTextures > 0) || (numWords > 0))
173
+        getLog() << "LoaderTR2: Found " << numAnimatedTextures << " Animated Textures!" << Log::endl;
174
+
161
     if (pos != numWords)
175
     if (pos != numWords)
162
-        getLog() << "LoaderTR2: Extra bytes at end of AnimatedTextures?" << Log::endl;
176
+        getLog() << "LoaderTR2: Extra bytes at end of AnimatedTextures?!" << Log::endl;
163
 }
177
 }
164
 
178
 
165
 // ---- Rooms ----
179
 // ---- Rooms ----
177
         // Number of data words (2 bytes) to follow
191
         // Number of data words (2 bytes) to follow
178
         uint32_t dataToFollow = file.readU32();
192
         uint32_t dataToFollow = file.readU32();
179
 
193
 
180
-
181
-        std::vector<struct vertex_t> vertices;
194
+        std::vector<vertex_t> vertices;
182
 
195
 
183
         uint16_t numVertices = file.readU16();
196
         uint16_t numVertices = file.readU16();
184
         for (unsigned int v = 0; v < numVertices; v++) {
197
         for (unsigned int v = 0; v < numVertices; v++) {
185
-            struct vertex_t vert;
198
+            vertex_t vert;
186
             // Vertex coordinates, relative to x/zOffset
199
             // Vertex coordinates, relative to x/zOffset
187
             vert.x = file.read16();
200
             vert.x = file.read16();
188
             vert.y = file.read16();
201
             vert.y = file.read16();
340
 
353
 
341
         getWorld().addRoom(room);
354
         getWorld().addRoom(room);
342
     }
355
     }
356
+
357
+    if (numRooms > 0)
358
+        getLog() << "LoaderTR2: Found " << numRooms << " Rooms!" << Log::endl;
359
+    else
360
+        getLog() << "LoaderTR2: No Rooms in this Level?!" << Log::endl;
343
 }
361
 }
344
 
362
 
345
 void LoaderTR2::loadFloorData() {
363
 void LoaderTR2::loadFloorData() {
389
         }
407
         }
390
         getWorld().addSprite(ss);
408
         getWorld().addSprite(ss);
391
     }
409
     }
410
+
411
+    if ((numSpriteTextures > 0) || (numSpriteSequences > 0))
412
+        getLog() << "LoaderTR2: Found " << numSpriteTextures << " Sprites in " << numSpriteSequences <<
413
+                 " Sequences!" << Log::endl;
414
+    else
415
+        getLog() << "LoaderTR2: No Sprites in this level?!" << Log::endl;
392
 }
416
 }
393
 
417
 
394
 // ---- Meshes ----
418
 // ---- Meshes ----
493
 
517
 
494
         // TODO store mesh data somewhere
518
         // TODO store mesh data somewhere
495
     }
519
     }
520
+
521
+    if (numMeshPointers > 0)
522
+        getLog() << "LoaderTR2: Found " << numMeshPointers << " Meshes, unimplemented!" << Log::endl;
496
 }
523
 }
497
 
524
 
498
 void LoaderTR2::loadStaticMeshes() {
525
 void LoaderTR2::loadStaticMeshes() {
528
 
555
 
529
     if (numStaticMeshes > 0)
556
     if (numStaticMeshes > 0)
530
         getLog() << "LoaderTR2: Found " << numStaticMeshes << " StaticMeshes, unimplemented!" << Log::endl;
557
         getLog() << "LoaderTR2: Found " << numStaticMeshes << " StaticMeshes, unimplemented!" << Log::endl;
558
+    else
559
+        getLog() << "LoaderTR2: No StaticMeshes in this level?!" << Log::endl;
531
 }
560
 }
532
 
561
 
533
 // ---- Moveables ----
562
 // ---- Moveables ----
534
 
563
 
564
+struct Animation_t {
565
+    uint32_t frameOffset;
566
+    uint8_t frameRate, frameSize;
567
+    uint16_t stateID, frameStart, frameEnd, nextAnimation;
568
+    uint16_t nextFrame, numStateChanges, stateChangeOffset;
569
+    uint16_t numAnimCommands, animCommandOffset;
570
+
571
+    Animation_t(uint32_t fo, uint8_t fr, uint8_t fs, uint16_t si,
572
+                uint16_t fst, uint16_t fe, uint16_t na, uint16_t nf,
573
+                uint16_t ns, uint16_t so, uint16_t nac, uint16_t ao)
574
+        : frameOffset(fo), frameRate(fr), frameSize(fs),
575
+          stateID(si), frameStart(fst), frameEnd(fe), nextAnimation(na),
576
+          nextFrame(nf), numStateChanges(ns), stateChangeOffset(so),
577
+          numAnimCommands(nac), animCommandOffset(ao) { }
578
+};
579
+
580
+struct StateChange_t {
581
+    uint16_t stateID, numAnimDispatches, animDispatchOffset;
582
+
583
+    StateChange_t(uint16_t s, uint16_t n, uint16_t a)
584
+        : stateID(s), numAnimDispatches(n), animDispatchOffset(a) { }
585
+};
586
+
587
+struct AnimDispatch_t {
588
+    int16_t low, high, nextAnimation, nextFrame;
589
+
590
+    AnimDispatch_t(int16_t l, int16_t h, int16_t na, int16_t nf)
591
+        : low(l), high(h), nextAnimation(na), nextFrame(nf) { }
592
+};
593
+
535
 void LoaderTR2::loadMoveables() {
594
 void LoaderTR2::loadMoveables() {
536
     uint32_t numAnimations = file.readU32();
595
     uint32_t numAnimations = file.readU32();
596
+    std::vector<Animation_t> animations;
537
     for (unsigned int a = 0; a < numAnimations; a++) {
597
     for (unsigned int a = 0; a < numAnimations; a++) {
538
         // *Byte* Offset into Frames[] (so divide by 2!)
598
         // *Byte* Offset into Frames[] (so divide by 2!)
539
         uint32_t frameOffset = file.readU32();
599
         uint32_t frameOffset = file.readU32();
559
         uint16_t numAnimCommands = file.readU16(); // How many animation commands to use
619
         uint16_t numAnimCommands = file.readU16(); // How many animation commands to use
560
         uint16_t animCommandOffset = file.readU16(); // Index into AnimCommand[]
620
         uint16_t animCommandOffset = file.readU16(); // Index into AnimCommand[]
561
 
621
 
562
-        // TODO store animations somewhere
622
+        animations.emplace_back(frameOffset, frameRate, frameSize,
623
+                                stateID, frameStart, frameEnd, nextAnimation, nextFrame, numStateChanges,
624
+                                stateChangeOffset, numAnimCommands, animCommandOffset);
563
     }
625
     }
564
 
626
 
627
+    if (numAnimations > 0)
628
+        getLog() << "LoaderTR2: Found " << numAnimations << " Animations!" << Log::endl;
629
+    else
630
+        getLog() << "LoaderTR2: No Animations in this level?!" << Log::endl;
631
+
565
     uint32_t numStateChanges = file.readU32();
632
     uint32_t numStateChanges = file.readU32();
633
+    std::vector<StateChange_t> stateChanges;
566
     for (unsigned int s = 0; s < numStateChanges; s++) {
634
     for (unsigned int s = 0; s < numStateChanges; s++) {
567
         uint16_t stateID = file.readU16();
635
         uint16_t stateID = file.readU16();
568
-        uint16_t numAnimDispatches = file.readU16();
636
+        uint16_t numAnimDispatches = file.readU16(); // Number of ranges (always 1..5?)
569
         uint16_t animDispatchOffset = file.readU16(); // Index into AnimDispatches[]
637
         uint16_t animDispatchOffset = file.readU16(); // Index into AnimDispatches[]
570
 
638
 
571
-        // TODO store state changes somewhere
639
+        stateChanges.emplace_back(stateID, numAnimDispatches, animDispatchOffset);
572
     }
640
     }
573
 
641
 
642
+    if (numStateChanges > 0)
643
+        getLog() << "LoaderTR2: Found " << numStateChanges << " StateChanges!" << Log::endl;
644
+    else
645
+        getLog() << "LoaderTR2: No StateChanges in this level?!" << Log::endl;
646
+
574
     uint32_t numAnimDispatches = file.readU32();
647
     uint32_t numAnimDispatches = file.readU32();
648
+    std::vector<AnimDispatch_t> animDispatches;
575
     for (unsigned int a = 0; a < numAnimDispatches; a++) {
649
     for (unsigned int a = 0; a < numAnimDispatches; a++) {
576
         int16_t low = file.read16(); // Lowest frame that uses this range
650
         int16_t low = file.read16(); // Lowest frame that uses this range
577
         int16_t high = file.read16(); // Highest frame (+1?) that uses this range
651
         int16_t high = file.read16(); // Highest frame (+1?) that uses this range
578
         int16_t nextAnimation = file.read16(); // Animation to go to
652
         int16_t nextAnimation = file.read16(); // Animation to go to
579
         int16_t nextFrame = file.read16(); // Frame offset to go to
653
         int16_t nextFrame = file.read16(); // Frame offset to go to
580
 
654
 
581
-        // TODO store animation dispatches somewhere
655
+        animDispatches.emplace_back(low, high, nextAnimation, nextFrame);
582
     }
656
     }
583
 
657
 
658
+    if (numAnimDispatches > 0)
659
+        getLog() << "LoaderTR2: Found " << numAnimDispatches << " AnimationDispatches!" << Log::endl;
660
+    else
661
+        getLog() << "LoaderTR2: No AnimationDispatches in this level?!" << Log::endl;
662
+
584
     uint32_t numAnimCommands = file.readU32();
663
     uint32_t numAnimCommands = file.readU32();
585
     std::vector<int16_t> animCommands;
664
     std::vector<int16_t> animCommands;
586
     for (unsigned int a = 0; a < numAnimCommands; a++) {
665
     for (unsigned int a = 0; a < numAnimCommands; a++) {
666
+        // A list of Opcodes with zero or more operands each,
667
+        // some referring to the whole animation (jump/grab points),
668
+        // some to specific frames (sound, bubbles, ...).
587
         animCommands.push_back(file.read16());
669
         animCommands.push_back(file.read16());
588
     }
670
     }
589
 
671
 
672
+    if (numAnimCommands > 0)
673
+        getLog() << "LoaderTR2: Found " << numAnimCommands << " AnimationCommands!" << Log::endl;
674
+    else
675
+        getLog() << "LoaderTR2: No AnimationCommands in this level?!" << Log::endl;
676
+
677
+    // This is really one uint32_t flags, followed by
678
+    // three int32_t x, y, z. However, we're given the number
679
+    // of 32bits, as well as byte indices later, so we store
680
+    // it as a single list of int32_t.
590
     uint32_t numMeshTrees = file.readU32();
681
     uint32_t numMeshTrees = file.readU32();
682
+    std::vector<int32_t> meshTrees;
591
     for (unsigned int m = 0; m < numMeshTrees; m++) {
683
     for (unsigned int m = 0; m < numMeshTrees; m++) {
592
         // 0x0002 - Put parent mesh on the mesh stack
684
         // 0x0002 - Put parent mesh on the mesh stack
593
         // 0x0001 - Pop mesh from stack, use as parent mesh
685
         // 0x0001 - Pop mesh from stack, use as parent mesh
594
         // When both are not set, use previous mesh as parent mesh
686
         // When both are not set, use previous mesh as parent mesh
595
         // When both are set, do 0x0001 first, then 0x0002, thereby
687
         // When both are set, do 0x0001 first, then 0x0002, thereby
596
         // reading the stack but not changing it
688
         // reading the stack but not changing it
597
-        uint32_t flags = file.readU32();
598
-
689
+        //uint32_t flags = file.readU32();
599
 
690
 
600
         // Offset of mesh origin from the parent mesh origin
691
         // Offset of mesh origin from the parent mesh origin
601
         //int32_t x = file.read32();
692
         //int32_t x = file.read32();
602
         //int32_t y = file.read32();
693
         //int32_t y = file.read32();
603
         //int32_t z = file.read32();
694
         //int32_t z = file.read32();
604
-        // Does not appear to be true...?
605
 
695
 
606
-        // TODO store mesh trees somewhere
696
+        meshTrees.push_back(file.read32());
607
     }
697
     }
608
 
698
 
699
+    if (numMeshTrees > 0)
700
+        getLog() << "LoaderTR2: Found " << numMeshTrees << " MeshTrees!" << Log::endl;
701
+    else
702
+        getLog() << "LoaderTR2: No MeshTrees in this level?!" << Log::endl;
703
+
609
     uint32_t numFrames = file.readU32();
704
     uint32_t numFrames = file.readU32();
610
     std::vector<uint16_t> frames;
705
     std::vector<uint16_t> frames;
611
     for (unsigned int f = 0; f < numFrames; f++) {
706
     for (unsigned int f = 0; f < numFrames; f++) {
707
+        // int16 bb1x, bb1y, bb1z
708
+        // int16 bb2x, bb2y, bb2z
709
+        // int16 offsetX, offsetY, offsetZ
710
+        // What follows next is a list of angles with numMeshes (from Moveable) entries.
711
+        // If the top bit (0x8000) of the first uint16 is set, a single X angle follows,
712
+        // if the second bit (0x4000) is set, a Y angle follows, both are a Z angle.
713
+        // If none is set, it's a three-axis rotation. The next 10 bits (0x3FF0) are
714
+        // the X rotation, the next 10 (0x000F 0xFC00) are Y, the next (0x03FF) are
715
+        // the Z rotation. The scaling is always 0x100->90deg.
716
+        // Rotation order: Y, X, Z!
612
         frames.push_back(file.readU16());
717
         frames.push_back(file.readU16());
613
     }
718
     }
614
 
719
 
720
+    if (numFrames > 0)
721
+        getLog() << "LoaderTR2: Found " << numFrames << " Frames!" << Log::endl;
722
+    else
723
+        getLog() << "LoaderTR2: No Frames in this level?!" << Log::endl;
724
+
615
     uint32_t numMoveables = file.readU32();
725
     uint32_t numMoveables = file.readU32();
616
     for (unsigned int m = 0; m < numMoveables; m++) {
726
     for (unsigned int m = 0; m < numMoveables; m++) {
617
         // Item identifier, matched in Items[]
727
         // Item identifier, matched in Items[]
620
         uint16_t startingMesh = file.readU16(); // Offset into MeshPointers[]
730
         uint16_t startingMesh = file.readU16(); // Offset into MeshPointers[]
621
         uint32_t meshTree = file.readU32(); // Offset into MeshTree[]
731
         uint32_t meshTree = file.readU32(); // Offset into MeshTree[]
622
         // *Byte* offset into Frames[] (divide by 2 for Frames[i])
732
         // *Byte* offset into Frames[] (divide by 2 for Frames[i])
623
-        uint32_t frameOffset = file.readU32();
733
+        uint32_t frameOffset = file.readU32(); // Only needed if no animation
624
 
734
 
625
         // If animation index is 0xFFFF, the object is stationary or
735
         // If animation index is 0xFFFF, the object is stationary or
626
         // animated by the engine (ponytail)
736
         // animated by the engine (ponytail)
627
         uint16_t animation = file.readU16();
737
         uint16_t animation = file.readU16();
628
 
738
 
629
-        // TODO store moveables somewhere
739
+        // TODO load all animations, not only the first frame!
740
+        //if (animation == 0xFFFF) {
741
+
742
+        // Just add the frame indicated in frameOffset, nothing else
743
+        char* tmp = reinterpret_cast<char*>(&frames[0]) + frameOffset;
744
+        BinaryMemory frame(tmp + 12, (numFrames * 2) - frameOffset - 12); // skip two BBs
745
+        float pos[3];
746
+        pos[0] = frame.read16();
747
+        pos[1] = frame.read16();
748
+        pos[2] = frame.read16();
749
+        BoneFrame* bf = new BoneFrame(pos);
750
+
751
+        for (int i = 0; i < numMeshes; i++) {
752
+            int mesh = startingMesh + i;
753
+            float offset[3] = { 0.0f, 0.0f, 0.0f };
754
+            float rotation[3] = { 0.0f, 0.0f, 0.0f };
755
+            char flag = (i == 0) ? 2 : 0;
756
+
757
+            // Nonprimary tag - positioned relative to first tag
758
+            if (i != 0) {
759
+                tmp = reinterpret_cast<char*>(&meshTrees[0]) + meshTree; // TODO (meshTree * 4)?
760
+                tmp += (i - 1) * 16; // TODO ?
761
+                BinaryMemory tree(tmp, (numMeshTrees * 4) - meshTree - ((i - 1) * 16));
762
+                flag = (char)tree.readU32();
763
+                offset[0] = tree.read32();
764
+                offset[1] = tree.read32();
765
+                offset[2] = tree.read32();
766
+
767
+                uint16_t a = frame.readU16();
768
+                if (a & 0xC000) {
769
+                    // Single angle
770
+                    int index = 0;
771
+                    if ((a & 0x8000) && (a & 0x4000))
772
+                        index = 2;
773
+                    else if (a & 0x4000)
774
+                        index = 1;
775
+                    rotation[index] = ((float)(a & 0x03FF)) * 360.0f / 1024.0f;
776
+                } else {
777
+                    // Three angles
778
+                    uint16_t b = frame.readU16();
779
+                    rotation[0] = (a & 0x3FF0) >> 4;
780
+                    rotation[1] = ((a & 0x000F) << 6) | ((b & 0xFC00) >> 10);
781
+                    rotation[2] = b & 0x03FF;
782
+                    for (int i = 0; i < 3; i++)
783
+                        rotation[i] = rotation[i] * 360.0f / 1024.0f;
784
+                }
785
+            }
786
+
787
+            BoneTag* bt = new BoneTag(mesh, offset, rotation, flag);
788
+            bf->add(bt);
789
+        }
790
+
791
+        AnimationFrame* af = new AnimationFrame(0);
792
+        af->add(bf);
793
+
794
+        SkeletalModel* sm = new SkeletalModel(objectID);
795
+        sm->add(af);
796
+        getWorld().addSkeletalModel(sm);
797
+
798
+        //} else {
799
+        // Add the whole animation hierarchy
800
+        //}
630
     }
801
     }
631
 
802
 
632
-    // TODO combine all this into moveables with their animations
803
+    if (numMoveables > 0)
804
+        getLog() << "LoaderTR2: Found " << numMoveables << " Moveables!" << Log::endl;
805
+    else
806
+        getLog() << "LoaderTR2: No Moveables in this level?!" << Log::endl;
633
 }
807
 }
634
 
808
 
635
 void LoaderTR2::loadItems() {
809
 void LoaderTR2::loadItems() {
651
         // 0x3E00 - Activation mask, open, can be XORed with related FloorData list fields.
825
         // 0x3E00 - Activation mask, open, can be XORed with related FloorData list fields.
652
         uint16_t flags = file.readU16();
826
         uint16_t flags = file.readU16();
653
 
827
 
654
-        // TODO store items somewhere
828
+        // TODO for now we're only creating Entities for each Moveable Item
829
+        for (int m = 0; m < getWorld().sizeSkeletalModel(); m++) {
830
+            if (getWorld().getSkeletalModel(m).getId() == objectID) {
831
+                float pos[3] = {
832
+                    static_cast<float>(x),
833
+                    static_cast<float>(y),
834
+                    static_cast<float>(z)
835
+                };
836
+
837
+                float rot[3] = {
838
+                    0.0f,
839
+                    OR_DEG_TO_RAD(((angle >> 14) & 0x03) * 90.0f),
840
+                    0.0f
841
+                };
842
+
843
+                Entity* e = new Entity(pos, rot, objectID, room, m);
844
+                getWorld().addEntity(e);
845
+
846
+                if (objectID == 0) {
847
+                    getGame().setLara(getWorld().sizeEntity() - 1);
848
+                }
849
+            }
850
+        }
655
     }
851
     }
656
 
852
 
657
     if (numItems > 0)
853
     if (numItems > 0)
658
         getLog() << "LoaderTR2: Found " << numItems << " Items, unimplemented!" << Log::endl;
854
         getLog() << "LoaderTR2: Found " << numItems << " Items, unimplemented!" << Log::endl;
855
+    else
856
+        getLog() << "LoaderTR2: No Items in this level?!" << Log::endl;
659
 }
857
 }
660
 
858
 
661
 void LoaderTR2::loadBoxesOverlapsZones() {
859
 void LoaderTR2::loadBoxesOverlapsZones() {

Loading…
Cancel
Save