starting world reading

This commit is contained in:
Ian Brown 2021-04-01 23:49:11 +01:00
parent 4ce3f37714
commit 85da6224e0
9 changed files with 203 additions and 14 deletions

View 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

View file

@ -5,16 +5,53 @@
class DataUtil
{
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);
}
static short getLEShort(const unsigned char* data, int offset){
static short getLEShort(const unsigned char* data, int 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);
}
static float getLEFloat(const unsigned char* data, int offset)
{
return *(float*)(data + offset);
}
private:
const unsigned char* p;
int offset;
};

View file

@ -7,6 +7,17 @@
class Mesh
{
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;
FloatVector* positions;
FloatVector* normals;

View file

@ -1,12 +1,21 @@
#pragma once
#include <vector>
class Texture;
class AnimData;
#include "Texture.h"
#include "AnimData.h"
class Mesh;
class TexturedMesh
{
public:
TexturedMesh() {
meshList = nullptr;
texture = nullptr;
}
~TexturedMesh() {
delete meshList; meshList = nullptr;
delete texture; texture = nullptr;
}
std::vector<Mesh*>* meshList;
Texture* texture;
};
@ -14,6 +23,12 @@ public:
class Model
{
public:
Model() {
animData = nullptr;
}
~Model() {
delete animData; animData = nullptr;
}
std::vector<TexturedMesh*> texturedMeshList;
AnimData* animData;
};

View file

@ -2,7 +2,7 @@
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){}
float x;
@ -10,6 +10,30 @@ struct FloatVector
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
{
ShortVector(short xx, short yy, short zz) : x(xx), y(yy), z(zz){}
@ -30,7 +54,7 @@ struct SByteVector
struct Point
{
Point(){}
Point() : x(0), y(0){}
Point(int xx, int yy) : x(xx), y(yy){}
int x;

View file

@ -18,10 +18,17 @@ World::~World()
{
delete patch;
}
for (auto& element : elements)
{
delete element;
}
}
TopoPatch::TopoPatch(int width, int height)
{
minHeight = 0;
maxHeight = 0;
x0 = y0 = 0;
w = width;
h = height;
heights = new int[w * h];
@ -29,5 +36,5 @@ TopoPatch::TopoPatch(int width, int height)
TopoPatch::~TopoPatch()
{
delete[] heights;
delete[] heights; heights = nullptr;
}

View file

@ -1,6 +1,9 @@
#pragma once
#include <vector>
#include <memory>
#include "VertexDefs.h"
#include "Model.h"
class TopoPatch
{
@ -18,13 +21,35 @@ class TopoElement
public:
int llx, lly, urx, ury;
int int8;
TopoPatch* patch;
std::shared_ptr<TopoPatch> patch;
int flags;
int x0, y0;
int baseHeight;
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
{
public:
@ -60,6 +85,9 @@ public:
// All of the topo patches. This collection owns the patches.
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.
std::vector<int> textureChunkOffsets;

View file

@ -2,6 +2,7 @@
#include "World.h"
#include "LmpRepository.h"
#include "DataUtil.h"
#include "VifDecoder.h"
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);
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)
@ -91,7 +152,7 @@ void WorldReader::decodeTopography(World* world, const unsigned char* data, int
int topoArrayOffset = DataUtil::getLEInt(data, 0x20);
// 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);
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 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->y0 = DataUtil::getLEInt(data, offset + 4);
patch->minHeight = DataUtil::getLEShort(data, offset + 0x10);

View file

@ -1,5 +1,6 @@
#pragma once
#include <memory>
#include "GameType.h"
class World;
@ -17,7 +18,7 @@ private:
void decodeWorldFile(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 readElements(World* world, const unsigned char* data, int dataLength, int elementBase, int numElements, int texMinx, int texMiny);
};