starting world reading
This commit is contained in:
parent
4ce3f37714
commit
85da6224e0
5
buildscripts/generate_vs2019_64_laptop.cmd
Normal file
5
buildscripts/generate_vs2019_64_laptop.cmd
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
@echo off
|
||||||
|
mkdir build_vs2019
|
||||||
|
pushd build_vs2019
|
||||||
|
"C:\Program Files\CMake\bin\cmake" -G "Visual Studio 16 2019" -A x64 -DADDITIONAL_FIND_PATH="C:\Qt6\6.0.2\msvc2019_64" -DVCPKG_TARGET_TRIPLET=x64-windows -DCMAKE_TOOLCHAIN_FILE="C:\dev\vcpkg\scripts\buildsystems\vcpkg.cmake" ../..
|
||||||
|
popd
|
|
@ -5,16 +5,53 @@
|
||||||
class DataUtil
|
class DataUtil
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int getLEInt(const unsigned char* data, int offset){
|
DataUtil(const unsigned char* p_in, int offset_in) : p(p_in), offset(offset_in)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float getLEFloat()
|
||||||
|
{
|
||||||
|
const float f = *(float*)(p + offset);
|
||||||
|
offset += 4;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLEInt()
|
||||||
|
{
|
||||||
|
const int i = *(int32_t*)(p + offset);
|
||||||
|
offset += 4;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short getLEUShort()
|
||||||
|
{
|
||||||
|
const unsigned short s = *(uint16_t*)(p + offset);
|
||||||
|
offset += 2;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getLEInt(const unsigned char* data, int offset)
|
||||||
|
{
|
||||||
return *(int32_t *)(data + offset);
|
return *(int32_t *)(data + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static short getLEShort(const unsigned char* data, int offset){
|
static short getLEShort(const unsigned char* data, int offset)
|
||||||
|
{
|
||||||
return *(int16_t *)(data + offset);
|
return *(int16_t *)(data + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned short getLEUShort(const unsigned char* data, int offset){
|
static unsigned short getLEUShort(const unsigned char* data, int offset)
|
||||||
|
{
|
||||||
return *(uint16_t *)(data + offset);
|
return *(uint16_t *)(data + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float getLEFloat(const unsigned char* data, int offset)
|
||||||
|
{
|
||||||
|
return *(float*)(data + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const unsigned char* p;
|
||||||
|
int offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,17 @@
|
||||||
class Mesh
|
class Mesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Mesh() {
|
||||||
|
positions = normals = nullptr;
|
||||||
|
uvCoords = nullptr;
|
||||||
|
numVertices = 0;
|
||||||
|
}
|
||||||
|
~Mesh() {
|
||||||
|
delete positions; positions = nullptr;
|
||||||
|
delete normals; normals = nullptr;
|
||||||
|
delete uvCoords; uvCoords = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<int> triangleIndices;
|
std::vector<int> triangleIndices;
|
||||||
FloatVector* positions;
|
FloatVector* positions;
|
||||||
FloatVector* normals;
|
FloatVector* normals;
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Texture;
|
#include "Texture.h"
|
||||||
class AnimData;
|
#include "AnimData.h"
|
||||||
|
class Mesh;
|
||||||
|
|
||||||
class TexturedMesh
|
class TexturedMesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
TexturedMesh() {
|
||||||
|
meshList = nullptr;
|
||||||
|
texture = nullptr;
|
||||||
|
}
|
||||||
|
~TexturedMesh() {
|
||||||
|
delete meshList; meshList = nullptr;
|
||||||
|
delete texture; texture = nullptr;
|
||||||
|
}
|
||||||
std::vector<Mesh*>* meshList;
|
std::vector<Mesh*>* meshList;
|
||||||
Texture* texture;
|
Texture* texture;
|
||||||
};
|
};
|
||||||
|
@ -14,6 +23,12 @@ public:
|
||||||
class Model
|
class Model
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Model() {
|
||||||
|
animData = nullptr;
|
||||||
|
}
|
||||||
|
~Model() {
|
||||||
|
delete animData; animData = nullptr;
|
||||||
|
}
|
||||||
std::vector<TexturedMesh*> texturedMeshList;
|
std::vector<TexturedMesh*> texturedMeshList;
|
||||||
AnimData* animData;
|
AnimData* animData;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
struct FloatVector
|
struct FloatVector
|
||||||
{
|
{
|
||||||
FloatVector(){}
|
FloatVector() : x(0.0f), y(0.0f), z(0.0f){}
|
||||||
FloatVector(float xx, float yy, float zz) : x(xx), y(yy), z(zz){}
|
FloatVector(float xx, float yy, float zz) : x(xx), y(yy), z(zz){}
|
||||||
|
|
||||||
float x;
|
float x;
|
||||||
|
@ -10,6 +10,30 @@ struct FloatVector
|
||||||
float z;
|
float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FloatRect
|
||||||
|
{
|
||||||
|
FloatRect() : x0(0.0f), y0(0.0f), x1(0.0f), y1(0.0f) {}
|
||||||
|
FloatRect(float xx0, float yy0, float xx1, float yy1) : x0(xx0), y0(yy0), x1(xx1), y1(yy1) {}
|
||||||
|
|
||||||
|
float x0;
|
||||||
|
float y0;
|
||||||
|
float x1;
|
||||||
|
float y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FloatBox
|
||||||
|
{
|
||||||
|
FloatBox() : x0(0.0f), y0(0.0f), z0(0.0f), x1(0.0f), y1(0.0f), z1(0.0f) {}
|
||||||
|
FloatBox(float xx0, float yy0, float zz0, float xx1, float yy1, float zz1) : x0(xx0), y0(yy0), z0(zz0), x1(xx1), y1(yy1), z1(zz1) {}
|
||||||
|
|
||||||
|
float x0;
|
||||||
|
float y0;
|
||||||
|
float z0;
|
||||||
|
float x1;
|
||||||
|
float y1;
|
||||||
|
float z1;
|
||||||
|
};
|
||||||
|
|
||||||
struct ShortVector
|
struct ShortVector
|
||||||
{
|
{
|
||||||
ShortVector(short xx, short yy, short zz) : x(xx), y(yy), z(zz){}
|
ShortVector(short xx, short yy, short zz) : x(xx), y(yy), z(zz){}
|
||||||
|
@ -30,7 +54,7 @@ struct SByteVector
|
||||||
|
|
||||||
struct Point
|
struct Point
|
||||||
{
|
{
|
||||||
Point(){}
|
Point() : x(0), y(0){}
|
||||||
Point(int xx, int yy) : x(xx), y(yy){}
|
Point(int xx, int yy) : x(xx), y(yy){}
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
|
|
|
@ -18,10 +18,17 @@ World::~World()
|
||||||
{
|
{
|
||||||
delete patch;
|
delete patch;
|
||||||
}
|
}
|
||||||
|
for (auto& element : elements)
|
||||||
|
{
|
||||||
|
delete element;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TopoPatch::TopoPatch(int width, int height)
|
TopoPatch::TopoPatch(int width, int height)
|
||||||
{
|
{
|
||||||
|
minHeight = 0;
|
||||||
|
maxHeight = 0;
|
||||||
|
x0 = y0 = 0;
|
||||||
w = width;
|
w = width;
|
||||||
h = height;
|
h = height;
|
||||||
heights = new int[w * h];
|
heights = new int[w * h];
|
||||||
|
@ -29,5 +36,5 @@ TopoPatch::TopoPatch(int width, int height)
|
||||||
|
|
||||||
TopoPatch::~TopoPatch()
|
TopoPatch::~TopoPatch()
|
||||||
{
|
{
|
||||||
delete[] heights;
|
delete[] heights; heights = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include "VertexDefs.h"
|
||||||
|
#include "Model.h"
|
||||||
|
|
||||||
class TopoPatch
|
class TopoPatch
|
||||||
{
|
{
|
||||||
|
@ -18,13 +21,35 @@ class TopoElement
|
||||||
public:
|
public:
|
||||||
int llx, lly, urx, ury;
|
int llx, lly, urx, ury;
|
||||||
int int8;
|
int int8;
|
||||||
TopoPatch* patch;
|
std::shared_ptr<TopoPatch> patch;
|
||||||
int flags;
|
int flags;
|
||||||
int x0, y0;
|
int x0, y0;
|
||||||
int baseHeight;
|
int baseHeight;
|
||||||
double cos_alpha, sin_alpha;
|
double cos_alpha, sin_alpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WorldElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FloatBox boundingBox;
|
||||||
|
TexturedMesh mesh;
|
||||||
|
|
||||||
|
// The position before rotation
|
||||||
|
FloatVector pos;
|
||||||
|
|
||||||
|
bool usesRotFlags;
|
||||||
|
int xyzRotFlags;
|
||||||
|
|
||||||
|
double cosAlpha;
|
||||||
|
double sinAlpha;
|
||||||
|
// Whether we should flip the y axis (when not using rot flags)
|
||||||
|
bool negYaxis;
|
||||||
|
|
||||||
|
// Store info to access again
|
||||||
|
int VifDataOffset;
|
||||||
|
int VifDataLength;
|
||||||
|
};
|
||||||
|
|
||||||
class World
|
class World
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -60,6 +85,9 @@ public:
|
||||||
// All of the topo patches. This collection owns the patches.
|
// All of the topo patches. This collection owns the patches.
|
||||||
std::vector<TopoPatch*> topoPatches;
|
std::vector<TopoPatch*> topoPatches;
|
||||||
|
|
||||||
|
// All of the elements. This collection owns the elements.
|
||||||
|
std::vector<WorldElement*> elements;
|
||||||
|
|
||||||
// The texture chunk offsets. 2D array with a 100 x 100 dimension.
|
// The texture chunk offsets. 2D array with a 100 x 100 dimension.
|
||||||
std::vector<int> textureChunkOffsets;
|
std::vector<int> textureChunkOffsets;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "LmpRepository.h"
|
#include "LmpRepository.h"
|
||||||
#include "DataUtil.h"
|
#include "DataUtil.h"
|
||||||
|
#include "VifDecoder.h"
|
||||||
|
|
||||||
World* WorldReader::readWorld(LmpRepository* lmpRepository, const char* name)
|
World* WorldReader::readWorld(LmpRepository* lmpRepository, const char* name)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +52,66 @@ void WorldReader::decodeWorldFile(World* world, const unsigned char* data, int d
|
||||||
int worldTexOffsetsOffset = DataUtil::getLEInt(data, 0x6C);
|
int worldTexOffsetsOffset = DataUtil::getLEInt(data, 0x6C);
|
||||||
|
|
||||||
readTextureChunkOffsets(world, data, dataLength, worldTexOffsetsOffset, texMinx, texMiny, texMaxx+1, texMaxy);
|
readTextureChunkOffsets(world, data, dataLength, worldTexOffsetsOffset, texMinx, texMiny, texMaxx+1, texMaxy);
|
||||||
|
readElements(world, data, dataLength, elementBase, numElements, texMinx, texMiny);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldReader::readElements(World* world, const unsigned char* data, int dataLength, int elementBase, int numElements, int texMinx, int texMiny)
|
||||||
|
{
|
||||||
|
for (int idx = 0; idx < numElements; ++idx) {
|
||||||
|
auto element = new WorldElement();
|
||||||
|
int elementSize = 0x38;
|
||||||
|
if (GameType::CHAMPIONS_RTA == gameType || GameType::JL_HEROES == gameType) {
|
||||||
|
elementSize = 0x3C;
|
||||||
|
}
|
||||||
|
int elementOffset = elementBase + idx * elementSize;
|
||||||
|
|
||||||
|
DataUtil reader(data, elementOffset);
|
||||||
|
|
||||||
|
int vifDataOffset = reader.getLEInt();
|
||||||
|
|
||||||
|
if (GameType::DARK_ALLIANCE == gameType) {
|
||||||
|
int Tex2 = reader.getLEInt();
|
||||||
|
}
|
||||||
|
int vifLen = reader.getLEInt();
|
||||||
|
float x1 = reader.getLEFloat();
|
||||||
|
float y1 = reader.getLEFloat();
|
||||||
|
float z1 = reader.getLEFloat();
|
||||||
|
float x2 = reader.getLEFloat();
|
||||||
|
float y2 = reader.getLEFloat();
|
||||||
|
float z2 = reader.getLEFloat();
|
||||||
|
|
||||||
|
element->boundingBox = FloatBox(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
|
||||||
|
|
||||||
|
int textureNum = reader.getLEInt() / 0x40;
|
||||||
|
|
||||||
|
int texCellxy = reader.getLEUShort();
|
||||||
|
int y = texCellxy / 100;
|
||||||
|
int x = texCellxy % 100;
|
||||||
|
if (GameType::CHAMPIONS_RTA == gameType || GameType::JL_HEROES == gameType) {
|
||||||
|
x += texMinx;
|
||||||
|
y += texMiny;
|
||||||
|
}
|
||||||
|
if (textureNum != 0) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
int texWidth = 100;
|
||||||
|
int texHeight = 100;
|
||||||
|
/*
|
||||||
|
if (element.Texture != null)
|
||||||
|
{
|
||||||
|
texWidth = element.Texture.PixelWidth;
|
||||||
|
texHeight = element.Texture.PixelHeight;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
unsigned char nregs = data[vifDataOffset + 0x10];
|
||||||
|
int vifStartOffset = (nregs + 2) * 0x10;
|
||||||
|
int vifDataLength = vifLen * 0x10 - vifStartOffset;
|
||||||
|
|
||||||
|
element->mesh.meshList = VifDecoder().decode(data, vifDataOffset + vifStartOffset);
|
||||||
|
|
||||||
|
|
||||||
|
world->elements.push_back(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldReader::readTextureChunkOffsets(World* world, const unsigned char* data, int dataLength, int worldTexOffsetsOffset, int texMinx, int texMiny, int texMaxx, int texMaxy)
|
void WorldReader::readTextureChunkOffsets(World* world, const unsigned char* data, int dataLength, int worldTexOffsetsOffset, int texMinx, int texMiny, int texMaxx, int texMaxy)
|
||||||
|
@ -91,7 +152,7 @@ void WorldReader::decodeTopography(World* world, const unsigned char* data, int
|
||||||
int topoArrayOffset = DataUtil::getLEInt(data, 0x20);
|
int topoArrayOffset = DataUtil::getLEInt(data, 0x20);
|
||||||
|
|
||||||
// Allows us to quickly look up patches from the offsets stored in the file.
|
// Allows us to quickly look up patches from the offsets stored in the file.
|
||||||
std::unordered_map<int, TopoPatch*> patchAddressMap;
|
std::unordered_map<int, std::shared_ptr<TopoPatch>> patchAddressMap;
|
||||||
|
|
||||||
world->topoElements.resize(numTopoElements);
|
world->topoElements.resize(numTopoElements);
|
||||||
for (int el = 0; el < numTopoElements; ++el){
|
for (int el = 0; el < numTopoElements; ++el){
|
||||||
|
@ -138,11 +199,11 @@ void WorldReader::decodeTopography(World* world, const unsigned char* data, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TopoPatch* WorldReader::readTopoPatch(const unsigned char* data, int offset)
|
std::shared_ptr<TopoPatch> WorldReader::readTopoPatch(const unsigned char* data, int offset)
|
||||||
{
|
{
|
||||||
int w = DataUtil::getLEInt(data, offset + 8);
|
int w = DataUtil::getLEInt(data, offset + 8);
|
||||||
int h = DataUtil::getLEInt(data, offset + 0x0c);
|
int h = DataUtil::getLEInt(data, offset + 0x0c);
|
||||||
TopoPatch* patch = new TopoPatch(w, h);
|
auto patch = std::make_shared<TopoPatch>(w, h);
|
||||||
patch->x0 = DataUtil::getLEInt(data, offset);
|
patch->x0 = DataUtil::getLEInt(data, offset);
|
||||||
patch->y0 = DataUtil::getLEInt(data, offset + 4);
|
patch->y0 = DataUtil::getLEInt(data, offset + 4);
|
||||||
patch->minHeight = DataUtil::getLEShort(data, offset + 0x10);
|
patch->minHeight = DataUtil::getLEShort(data, offset + 0x10);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include "GameType.h"
|
#include "GameType.h"
|
||||||
|
|
||||||
class World;
|
class World;
|
||||||
|
@ -17,7 +18,7 @@ private:
|
||||||
|
|
||||||
void decodeWorldFile(World* world, const unsigned char* data, int dataLength);
|
void decodeWorldFile(World* world, const unsigned char* data, int dataLength);
|
||||||
void decodeTopography(World* world, const unsigned char* data, int dataLength);
|
void decodeTopography(World* world, const unsigned char* data, int dataLength);
|
||||||
TopoPatch* readTopoPatch(const unsigned char* data, int offset);
|
std::shared_ptr<TopoPatch> readTopoPatch(const unsigned char* data, int offset);
|
||||||
void readTextureChunkOffsets(World* world, const unsigned char* data, int dataLength, int worldTexOffsetsOffset, int texMinx, int texMiny, int texMaxx, int texMaxy);
|
void readTextureChunkOffsets(World* world, const unsigned char* data, int dataLength, int worldTexOffsetsOffset, int texMinx, int texMiny, int texMaxx, int texMaxy);
|
||||||
|
void readElements(World* world, const unsigned char* data, int dataLength, int elementBase, int numElements, int texMinx, int texMiny);
|
||||||
};
|
};
|
Reference in a new issue