More land and cell work

This commit is contained in:
Alexander "Ace" Olofsson 2012-06-11 20:02:03 +02:00
parent f675d8d039
commit 76c4aa41bb
4 changed files with 60 additions and 28 deletions

View file

@ -9,7 +9,7 @@ namespace ESM
void CellRef::save(ESMWriter &esm) void CellRef::save(ESMWriter &esm)
{ {
esm.writeHNT("FRMR", refnum); esm.writeHNT("FRMR", refnum);
esm.writeHNString("NAME", refID); esm.writeHNCString("NAME", refID);
if (scale != 1.0) if (scale != 1.0)
esm.writeHNT("XSCL", scale); esm.writeHNT("XSCL", scale);
@ -33,7 +33,7 @@ void CellRef::save(ESMWriter &esm)
if (teleport) if (teleport)
{ {
esm.writeHNT("DODT", doorDest); esm.writeHNT("DODT", doorDest);
esm.writeHNOString("DNAM", destCell); esm.writeHNOCString("DNAM", destCell);
} }
if (lockLevel != 0) if (lockLevel != 0)
@ -60,6 +60,7 @@ void Cell::load(ESMReader &esm)
// Water level // Water level
water = 0; water = 0;
NAM0 = 0;
if (data.flags & Interior) if (data.flags & Interior)
{ {
@ -87,6 +88,8 @@ void Cell::load(ESMReader &esm)
region = esm.getHNOString("RGNN"); region = esm.getHNOString("RGNN");
esm.getHNOT(mapColor, "NAM5"); esm.getHNOT(mapColor, "NAM5");
} }
if (esm.isNextSub("NAM0"))
esm.getHT(NAM0);
// Save position of the cell references and move on // Save position of the cell references and move on
context = esm.getContext(); context = esm.getContext();
@ -112,6 +115,9 @@ void Cell::save(ESMWriter &esm)
if (mapColor != 0) if (mapColor != 0)
esm.writeHNT("NAM5", mapColor); esm.writeHNT("NAM5", mapColor);
} }
if (NAM0 != 0)
esm.writeHNT("NAM0", NAM0);
} }
void Cell::restore(ESMReader &esm) const void Cell::restore(ESMReader &esm) const
@ -141,9 +147,10 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
// Number of references in the cell? Maximum once in each cell, // Number of references in the cell? Maximum once in each cell,
// but not always at the beginning, and not always right. In other // but not always at the beginning, and not always right. In other
// words, completely useless. // words, completely useless.
if (esm.isNextSub("NAM0"))
{ {
int i; esm.skipHSubSize(4);
esm.getHNOT(i, "NAM0"); //esm.getHNOT(NAM0, "NAM0");
} }
esm.getHNT(ref.refnum, "FRMR"); esm.getHNT(ref.refnum, "FRMR");

View file

@ -120,6 +120,7 @@ struct Cell : public Record
AMBIstruct ambi; AMBIstruct ambi;
float water; // Water level float water; // Water level
int mapColor; int mapColor;
int NAM0;
void load(ESMReader &esm); void load(ESMReader &esm);
void save(ESMWriter &esm); void save(ESMWriter &esm);

View file

@ -7,11 +7,18 @@ void Land::LandData::save(ESMWriter &esm)
{ {
// TODO: Make this actually work. // TODO: Make this actually work.
//esm.writeHNT("VNML", normals, sizeof(VNML)); esm.writeHNT("VNML", normals, sizeof(VNML));
esm.writeHNT("VHGT", heights, sizeof(VHGT)); esm.writeHNT("VHGT", heights, sizeof(VHGT));
esm.writeHNT("WNAM", 0, 81); //esm.writeHNT("WNAM", 0, 81);
esm.writeHNT("VCLR", colours, 3*LAND_NUM_VERTS); esm.startSubRecord("WNAM");
esm.writeHNT("VTEX", textures, 512); for (int i = 0; i < 81; i++)
esm.writeT((char)0x80, 1);
esm.endRecord("WNAM");
if (dataTypes & Land::DATA_VCLR)
esm.writeHNT("VCLR", colours, 3*LAND_NUM_VERTS);
if (dataTypes & Land::DATA_VTEX)
esm.writeHNT("VTEX", textures, 512);
} }
Land::Land() Land::Land()
@ -19,7 +26,8 @@ Land::Land()
, X(0) , X(0)
, Y(0) , Y(0)
, mEsm(NULL) , mEsm(NULL)
, hasData(false) // , hasData(false)
, dataTypes(0)
, dataLoaded(false) , dataLoaded(false)
, landData(NULL) , landData(NULL)
{ {
@ -30,7 +38,6 @@ Land::~Land()
delete landData; delete landData;
} }
void Land::load(ESMReader &esm) void Land::load(ESMReader &esm)
{ {
mEsm = &esm; mEsm = &esm;
@ -47,36 +54,37 @@ void Land::load(ESMReader &esm)
context = esm.getContext(); context = esm.getContext();
hasData = false; hasData = false;
int cnt = 0;
// Skip these here. Load the actual data when the cell is loaded. // Skip these here. Load the actual data when the cell is loaded.
if (esm.isNextSub("VNML")) if (esm.isNextSub("VNML"))
{ {
esm.skipHSubSize(12675); esm.skipHSubSize(12675);
cnt++; dataTypes |= DATA_VNML;
} }
if (esm.isNextSub("VHGT")) if (esm.isNextSub("VHGT"))
{ {
esm.skipHSubSize(4232); esm.skipHSubSize(4232);
cnt++; dataTypes |= DATA_VHGT;
} }
if (esm.isNextSub("WNAM")) if (esm.isNextSub("WNAM"))
{ {
esm.skipHSubSize(81); esm.skipHSubSize(81);
dataTypes |= DATA_WNAM;
} }
if (esm.isNextSub("VCLR")) if (esm.isNextSub("VCLR"))
{ {
esm.skipHSubSize(12675); esm.skipHSubSize(12675);
dataTypes |= DATA_VCLR;
} }
if (esm.isNextSub("VTEX")) if (esm.isNextSub("VTEX"))
{ {
esm.skipHSubSize(512); esm.skipHSubSize(512);
cnt++; dataTypes |= DATA_VTEX;
} }
// We need all three of VNML, VHGT and VTEX in order to use the // We need all three of VNML, VHGT and VTEX in order to use the
// landscape. // landscape. (Though Morrowind seems to accept terrain without VTEX/VCLR entries)
hasData = (cnt == 3); hasData = dataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM);
dataLoaded = false; dataLoaded = false;
landData = NULL; landData = NULL;
@ -101,7 +109,7 @@ void Land::save(ESMWriter &esm)
landData->save(esm); landData->save(esm);
if (!wasLoaded) if (!wasLoaded)
unloadData(); unloadData(); // Don't need to keep the data loaded if it wasn't already
} }
void Land::loadData() void Land::loadData()
@ -117,6 +125,8 @@ void Land::loadData()
{ {
mEsm->restoreContext(context); mEsm->restoreContext(context);
memset(landData->normals, 0, LAND_NUM_VERTS * 3);
//esm.getHNExact(landData->normals, sizeof(VNML), "VNML"); //esm.getHNExact(landData->normals, sizeof(VNML), "VNML");
if (mEsm->isNextSub("VNML")) if (mEsm->isNextSub("VNML"))
{ {
@ -151,16 +161,19 @@ void Land::loadData()
}else{ }else{
landData->usingColours = false; landData->usingColours = false;
} }
//TODO fix magic numbers if (mEsm->isNextSub("VTEX"))
uint16_t vtex[512]; {
mEsm->getHNExact(&vtex, 512, "VTEX"); //TODO fix magic numbers
uint16_t vtex[512];
mEsm->getHExact(&vtex, 512);
int readPos = 0; //bit ugly, but it works int readPos = 0; //bit ugly, but it works
for ( int y1 = 0; y1 < 4; y1++ ) for ( int y1 = 0; y1 < 4; y1++ )
for ( int x1 = 0; x1 < 4; x1++ ) for ( int x1 = 0; x1 < 4; x1++ )
for ( int y2 = 0; y2 < 4; y2++) for ( int y2 = 0; y2 < 4; y2++)
for ( int x2 = 0; x2 < 4; x2++ ) for ( int x2 = 0; x2 < 4; x2++ )
landData->textures[(y1*4+y2)*16+(x1*4+x2)] = vtex[readPos++]; landData->textures[(y1*4+y2)*16+(x1*4+x2)] = vtex[readPos++];
}
} }
else else
{ {
@ -172,6 +185,7 @@ void Land::loadData()
} }
} }
landData->dataTypes = dataTypes;
dataLoaded = true; dataLoaded = true;
} }

View file

@ -26,9 +26,18 @@ struct Land : public Record
ESM_Context context; ESM_Context context;
bool hasData; bool hasData;
int dataTypes;
bool dataLoaded; bool dataLoaded;
enum
{
DATA_VNML = 1,
DATA_VHGT = 2,
DATA_WNAM = 4,
DATA_VCLR = 8,
DATA_VTEX = 16
};
// number of vertices per side // number of vertices per side
static const int LAND_SIZE = 65; static const int LAND_SIZE = 65;
@ -62,11 +71,12 @@ struct Land : public Record
{ {
float heightOffset; float heightOffset;
float heights[LAND_NUM_VERTS]; float heights[LAND_NUM_VERTS];
//float normals[LAND_NUM_VERTS * 3]; VNML normals;
uint16_t textures[LAND_NUM_TEXTURES]; uint16_t textures[LAND_NUM_TEXTURES];
bool usingColours; bool usingColours;
char colours[3 * LAND_NUM_VERTS]; char colours[3 * LAND_NUM_VERTS];
int dataTypes;
void save(ESMWriter &esm); void save(ESMWriter &esm);
}; };