aboutsummaryrefslogtreecommitdiff
path: root/src/shared/vmap/TileAssembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/vmap/TileAssembler.cpp')
-rw-r--r--src/shared/vmap/TileAssembler.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/shared/vmap/TileAssembler.cpp b/src/shared/vmap/TileAssembler.cpp
index 509696f39a2..75997a847a2 100644
--- a/src/shared/vmap/TileAssembler.cpp
+++ b/src/shared/vmap/TileAssembler.cpp
@@ -17,20 +17,27 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include <G3D/Vector3.h>
#include <G3D/Triangle.h>
+
#include "TileAssembler.h"
#include "CoordModelMapping.h"
#include "ModelContainer.h"
+
#include <limits.h>
#include <string.h>
+
#ifdef _ASSEMBLER_DEBUG
FILE *g_df = NULL;
#endif
+
using namespace G3D;
+
namespace VMAP
{
//=================================================================
+
Vector3 ModelPosition::transform(const Vector3& pIn) const
{
//return(pIn);
@@ -39,8 +46,10 @@ namespace VMAP
out = ixMatrix * out;
out = iyMatrix * out;
return(out);
+
}
//=================================================================
+
TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
{
iCurrentUniqueNameId = 0;
@@ -50,12 +59,16 @@ namespace VMAP
//mkdir(iDestDir);
init();
}
+
//=================================================================
+
TileAssembler::~TileAssembler()
{
delete iCoordModelMapping;
}
+
//=================================================================
+
void TileAssembler::init()
{
iCoordModelMapping = new CoordModelMapping();
@@ -65,16 +78,20 @@ namespace VMAP
addWorldAreaMapId(571); //Expansion02
}
//=================================================================
+
std::string getModNameFromModPosName(const std::string& pModPosName)
{
size_t spos = pModPosName.find_first_of('#');
std::string modelFileName = pModPosName.substr(0,spos);
return(modelFileName);
}
+
//=================================================================
+
unsigned int TileAssembler::getUniqueNameId(const std::string pName)
{
unsigned int result;
+
if(!iUniqueNameIds.containsKey(pName))
{
++iCurrentUniqueNameId;
@@ -83,11 +100,14 @@ namespace VMAP
result = iUniqueNameIds.get(pName);
return result;
}
+
//=================================================================
+
std::string TileAssembler::getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName)
{
size_t spos;
char buffer[20];
+
std::string modelFileName = getModNameFromModPosName(pModPosName);
//std::string fext = pModPosName.substr(modelFileName.length(),pModPosName.length());
unsigned int fextId = getUniqueNameId(pModPosName);
@@ -105,7 +125,9 @@ namespace VMAP
dirEntry.append(".vmap");
return(dirEntry);
}
+
//=================================================================
+
void emptyArray(Array<ModelContainer*>& mc)
{
int no=mc.size();
@@ -116,6 +138,7 @@ namespace VMAP
mc.remove(no);
}
}
+
//=================================================================
bool TileAssembler::convertWorld()
{
@@ -126,22 +149,27 @@ namespace VMAP
::g_df = fopen("../TileAssembler_release.txt", "wb");
# endif
#endif
+
std::string fname = iSrcDir;
fname.append("/");
fname.append("dir");
iCoordModelMapping->setModelNameFilterMethod(iFilterMethod);
+
printf("Read coordinate mapping...\n");
if(!iCoordModelMapping->readCoordinateMapping(fname))
return false;
+
Array<unsigned int> mapIds = iCoordModelMapping->getMaps();
if(mapIds.size() == 0)
{
printf("Fatal error: empty map list!\n");
return false;
}
+
for(int i=0; i<mapIds.size(); ++i)
{
unsigned int mapId = mapIds[i];
+
#ifdef _ASSEMBLER_DEBUG
if(mapId == 0) // "Azeroth" just for debug
{
@@ -172,12 +200,15 @@ namespace VMAP
{
sprintf(buffer, "%03u",mapId);
dirname = std::string(buffer);
+
// prevent spam for small maps
if(x==0 && y==0)
printf("%s...\n",dirname.c_str());
}
+
bool result = fillModelContainerArray(dirname, mapId, x, y, mc);
emptyArray(mc);
+
if(!result)
return false;
}
@@ -187,15 +218,20 @@ namespace VMAP
#ifdef _ASSEMBLER_DEBUG
if(::g_df) fclose(::g_df);
#endif
+
return true;
}
+
//=================================================================
+
bool TileAssembler::fillModelContainerArray(const std::string& pDirFileName, unsigned int pMapId, int pXPos, int pYPos, Array<ModelContainer*>& pMC)
{
ModelContainer* modelContainer;
+
NameCollection nameCollection = iCoordModelMapping->getFilenamesForCoordinate(pMapId, pXPos, pYPos);
if(nameCollection.size() == 0)
return true; // no data...
+
char dirfilename[500];
sprintf(dirfilename,"%s/%s.vmdir",iDestDir.c_str(),pDirFileName.c_str());
FILE *dirfile = fopen(dirfilename, "ab");
@@ -204,8 +240,10 @@ namespace VMAP
printf("ERROR: Can't create file %s",dirfilename);
return false;
}
+
char destnamebuffer[500];
char fullnamedestnamebuffer[500];
+
if(nameCollection.iMainFiles.size() >0)
{
sprintf(destnamebuffer,"%03u_%i_%i.vmap",pMapId, pYPos, pXPos); // flip it here too
@@ -241,8 +279,10 @@ namespace VMAP
iCoordModelMapping->addAlreadyProcessedSingleFile(checkDoubleStr);
fprintf(dirfile, "%s\n",dirEntryName.c_str());
destFileName.append(dirEntryName);
+
Array<std::string> positionarray;
positionarray.append(nameCollection.iSingeFiles[pos]);
+
if(!iCoordModelMapping->isAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]))
{
modelContainer = processNames(positionarray, destFileName.c_str());
@@ -255,10 +295,13 @@ namespace VMAP
}
++pos;
}
+
fclose(dirfile);
return true;
}
+
//=================================================================
+
void removeEntriesFromTree(AABSPTree<SubModel *>* pTree)
{
Array<SubModel *> submodelArray;
@@ -270,18 +313,24 @@ namespace VMAP
delete submodelArray[no];
}
}
+
//=================================================================
+
ModelContainer* TileAssembler::processNames(const Array<std::string>& pPositions, const char* pDestFileName)
{
ModelContainer *modelContainer = 0;
+
Vector3 basepos = Vector3(0,0,0);
AABSPTree<SubModel *>* mainTree = new AABSPTree<SubModel *>();
+
int pos = 0;
+
bool result = true;
while(result && (pos < pPositions.size()))
{
std::string modelPosString = pPositions[pos];
std::string modelFileName = getModNameFromModPosName(modelPosString);
+
if(!fillModelIntoTree(mainTree, basepos, modelPosString, modelFileName))
{
result = false;
@@ -296,9 +345,12 @@ namespace VMAP
modelContainer->writeFile(pDestFileName);
}
removeEntriesFromTree(mainTree);
+
delete mainTree;
+
return(modelContainer);
}
+
//=================================================================
bool TileAssembler::readRawFile(std::string& pModelFilename, ModelPosition& pModelPosition, AABSPTree<SubModel *> *pMainTree)
{
@@ -317,14 +369,18 @@ namespace VMAP
filename.append(baseModelFilename);
rf = fopen(filename.c_str(), "rb");
}
+
if(!rf)
{
printf("ERROR: Can't open model file in form: %s",pModelFilename.c_str());
printf("... or form: %s",filename.c_str() );
return false;
}
+
char ident[8];
+
int trianglecount =0;
+
#ifdef _ASSEMBLER_DEBUG
int startgroup = 0; //2;
int endgroup = INT_MAX; //2;
@@ -335,11 +391,13 @@ namespace VMAP
int startgroup = 0;
int endgroup = INT_MAX;
#endif
+
// temporary use defines to simplify read/check code (close file and return at fail)
#define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \
fclose(rf); return(false); }
#define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \
fclose(rf); return(false); }
+
READ_OR_RETURN(&ident, 8);
if(strcmp(ident, "VMAP001") == 0)
{
@@ -350,6 +408,7 @@ namespace VMAP
// we have to read one int. This is needed during the export and we have to skip it here
int tempNVectors;
READ_OR_RETURN(&tempNVectors, sizeof(int));
+
}
else
{
@@ -361,13 +420,17 @@ namespace VMAP
char blockId[5];
blockId[4] = 0;
int blocksize;
+
READ_OR_RETURN(&groups, sizeof(G3D::uint32));
+
for(int g=0;g<(int)groups;g++)
{
// group MUST NOT have more then 65536 indexes !! Array will have a problem with that !! (strange ...)
Array<int> tempIndexArray;
Array<Vector3> tempVertexArray;
+
AABSPTree<Triangle> *gtree = new AABSPTree<Triangle>();
+
// add free gtree at fail
#undef READ_OR_RETURN
#undef CMP_OR_RETURN
@@ -375,8 +438,10 @@ namespace VMAP
fclose(rf); delete gtree; return(false); }
#define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \
fclose(rf); delete gtree; return(false); }
+
G3D::uint32 flags;
READ_OR_RETURN(&flags, sizeof(G3D::uint32));
+
G3D::uint32 branches;
READ_OR_RETURN(&blockId, 4);
CMP_OR_RETURN(blockId, "GRP ");
@@ -388,6 +453,7 @@ namespace VMAP
// indexes for each branch (not used jet)
READ_OR_RETURN(&indexes, sizeof(G3D::uint32));
}
+
// ---- indexes
READ_OR_RETURN(&blockId, 4);
CMP_OR_RETURN(blockId, "INDX");
@@ -405,13 +471,16 @@ namespace VMAP
}
delete[] indexarray;
}
+
// ---- vectors
READ_OR_RETURN(&blockId, 4);
CMP_OR_RETURN(blockId, "VERT");
READ_OR_RETURN(&blocksize, sizeof(int));
unsigned int nvectors;
READ_OR_RETURN(&nvectors, sizeof(int));
+
float *vectorarray = 0;
+
// add vectorarray free
#undef READ_OR_RETURN
#undef CMP_OR_RETURN
@@ -419,6 +488,7 @@ namespace VMAP
fclose(rf); delete gtree; delete[] vectorarray; return(false); }
#define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \
fclose(rf); delete gtree; delete[] vectorarray; return(false); }
+
if(nvectors >0)
{
vectorarray = new float[nvectors*sizeof(float)*3];
@@ -434,22 +504,27 @@ namespace VMAP
fseek(rf, blocksize, SEEK_CUR);
}
+
for(unsigned int i=0, indexNo=0; indexNo<nvectors; indexNo++)
{
Vector3 v = Vector3(vectorarray[i+2], vectorarray[i+1], vectorarray[i+0]);
i+=3;
v = pModelPosition.transform(v);
+
float swapy = v.y;
v.y = v.x;
v.x = swapy;
+
tempVertexArray.append(v);
}
+
// ---- calculate triangles
int rest = nindexes%3;
if(rest != 0)
{
nindexes -= rest;
}
+
for(unsigned int i=0;i<(nindexes);)
{
Triangle t = Triangle(tempVertexArray[tempIndexArray[i+2]], tempVertexArray[tempIndexArray[i+1]], tempVertexArray[tempIndexArray[i+0]] );
@@ -460,13 +535,16 @@ namespace VMAP
gtree->insert(t);
}
}
+
// drop of temporary use defines
#undef READ_OR_RETURN
#undef CMP_OR_RETURN
+
if(vectorarray != 0)
{
delete vectorarray;
}
+
if(gtree->size() >0)
{
gtree->balance();
@@ -486,31 +564,40 @@ namespace VMAP
fclose(rf);
return true;
}
+
//=================================================================
+
bool TileAssembler::fillModelIntoTree(AABSPTree<SubModel *> *pMainTree, const Vector3& pBasePos, std::string& pPos, std::string& pModelFilename)
{
ModelPosition modelPosition;
getModelPosition(pPos, modelPosition);
// all should be relative to object base position
modelPosition.moveToBasePos(pBasePos);
+
modelPosition.init();
+
return readRawFile(pModelFilename, modelPosition, pMainTree);
}
+
//=================================================================
void TileAssembler::getModelPosition(std::string& pPosString, ModelPosition& pModelPosition)
{
float vposarray[3];
float vdirarray[3];
float scale;
+
size_t spos = pPosString.find_first_of('#');
std::string stripedPosString = pPosString.substr(spos+1,pPosString.length());
+
sscanf(stripedPosString.c_str(), "%f,%f,%f_%f,%f,%f_%f",
&vposarray[0],&vposarray[1],&vposarray[2],
&vdirarray[0],&vdirarray[1],&vdirarray[2],
&scale);
+
pModelPosition.iPos = Vector3(vposarray[0], vposarray[1], vposarray[2]);
pModelPosition.iDir = Vector3(vdirarray[0], vdirarray[1], vdirarray[2]);
pModelPosition.iScale = scale;
+
}
//==========================================
} // VMAP