svn -> git Migration

This commit is contained in:
KimLS
2013-02-16 16:14:39 -08:00
parent 88c9715fb0
commit da7347f76f
1174 changed files with 445622 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
#ifndef __OPENEQ_THREED__
#define __OPENEQ_THREED__
#include "3d_base.hpp"
class Octree_Node;
class Bone {
public:
char *name;
int bone1, bone2;
float x, y, z;
float e[4];
float scale[3];
int vert_count;
int *verts;
};
class Zone_Model {
public:
Zone_Model() {}
~Zone_Model() {}
Vertex **verts;
Polygon **polys;
Octree_Node *octree;
Texture **tex;
int vert_count, poly_count, tex_count;
};
class MobModel {
public:
MobModel() {}
~MobModel() {}
Vertex **verts;
Polygon **polys;
Texture **tex;
int vert_count, poly_count, tex_count;
Bone *bones;
int bone_count;
};
class Content_3D {
public:
Content_3D() { this->mob_model_count = 0; this->mob_count = 0; }
~Content_3D() {}
Model *GetModel(char *model_name);
void GenerateOctree();
void MergeTextures();
void MergeTexturesLazy();
Zone_Model *zone_model;
Model **models;
Placeable **placeable;
int model_count, plac_count; // Count of placeable object models and count of instances
MobModel **mob_models;
Placeable **mob_locs;
int mob_model_count, mob_count;
};
#endif
+73
View File
@@ -0,0 +1,73 @@
#ifndef __OPENEQ_THREED_BASE__
#define __OPENEQ_THREED_BASE__
#pragma pack(1)
#include "archive.hpp"
struct Light {
float x, y, z;
float r, g, b;
float rad;
} typedef Light;
struct Vertex {
float x, y, z;
float i, j, k;
float u, v;
int bone;
} typedef Vertex;
struct Polygon {
int flags;
int v1, v2, v3;
int tex;
} typedef Polygon;
struct Texture {
Archive *archive;
char frame_count;
char current_frame;
uint32 *tex;
char **filenames;
char flags;
} typedef Texture;
class Model {
public:
Model() {}
~Model() {}
Vertex **verts;
Polygon **polys;
Texture **tex;
int vert_count, poly_count, tex_count;
char *name;
};
class Placeable {
public:
float x, y, z;
float rx, ry, rz;
float scale[3];
int model;
char rendered;
Vertex bounds[8];
void CalculateBoundaries(Model *model);
};
#pragma pack()
#endif
+146
View File
@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="Azone"
ProjectGUID="{64F17C8F-6D9A-42E9-B2CE-DA5073885E72}"
RootNamespace="Azone"
Keyword="ManagedCProj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
ManagedExtensions="FALSE">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG"
MinimalRebuild="FALSE"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
WarningLevel="3"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="zlib.lib"
OutputFile="$(OutDir)\$(ProjectName).exe"
LinkIncremental="2"
IgnoreDefaultLibraryNames="MSVCRT"
GenerateDebugInformation="TRUE"
AssemblyDebug="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
ManagedExtensions="FALSE">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG"
MinimalRebuild="FALSE"
RuntimeLibrary="0"
WarningLevel="3"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\$(ProjectName).exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\azone.cpp">
</File>
<File
RelativePath=".\s3d.c">
</File>
<File
RelativePath=".\wld.c">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\azone.h">
</File>
<File
RelativePath=".\s3d.h">
</File>
<File
RelativePath=".\types.h">
</File>
<File
RelativePath=".\wld.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+24
View File
@@ -0,0 +1,24 @@
Father Nitwit's Zone file converter
purpose: convert 23d files into .map files for LOS
If there are any 3d math folks reading this who know how to figure out
if a 3d triangle passes through a 3d, infinitely tall box (bounded x,y),
please let me know. The code in the converter dosent work right now, and
has been 'commented' out with the return on line 717 of azone.cpp
This does not work on windows, if you get it working, please let me know how.
You need to use a unix box to convert your map files, then the .maps should work
on your windows server.
how to use it:
built it with make
upload your s3d files into a directory.
You do not need the _obj or _chr files, just the zone.s3d files.
copy the azone binary to that directory.
run it on each map file:
example: converting gfaydark
./azone gfaydark
this will read gfaydark.s3d and produce gfaydark.map
put these map files into Maps/ in your eqemu running directory.
+32
View File
@@ -0,0 +1,32 @@
#ifndef __OPENEQ_ARCHIVE_API__
#define __OPENEQ_ARCHIVE_API__
#include "global.hpp"
#include <stdio.h>
class Archive {
public:
Archive() {}
virtual ~Archive() {}
virtual int Open(FILE *fp) = 0;
virtual int Close() = 0;
virtual int GetFile(char *name, uchar **buf, int *len) = 0;
virtual const char *FindExtension(const char *ext) = 0;
char **filenames;
int count;
protected:
uchar *buffer;
int buf_len;
int status;
uint32 *files;
FILE *fp;
};
#endif
+362
View File
@@ -0,0 +1,362 @@
/*
Father Nitwit's Zone to map conversion program.
Copyright (C) 2004 Father Nitwit (eqemu@8ass.com)
This thing uses code from freaku, so whatever license that comes under
is relavent, if you care.
the rest of it is GPL, even though I hate the GPL.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef short SHORT;
typedef unsigned long DWORD;
#include <stdio.h>
#include <string.h>
#include <math.h>
//#include "EQWldData.h"
#include "awater.h"
#include "types.h"
#include "s3d.h"
#include "wld.h"
#include "archive.hpp"
#include "pfs.hpp"
#include "file_loader.hpp"
#include "zon.hpp"
#include "ter.hpp"
//this un-commented works with my map.cpp code correctly.
//with both of my inverts there commented.
#define INVERSEXY 1
#include <vector>
#include <map>
using namespace std;
//#define SPLIT_DEBUG
bool BuildWaterMap(const char *shortname, long DefaultRegionType);
void PrintBSP(BSP_Node *tree, long node_number);
long BSPFindRegion(BSP_Node *tree, long node_number, long region);
long BSPFindNode(BSP_Node *tree, long node_number, float x, float y, float z);
long BSPMarkRegion(BSP_Node *tree, long node_number, long region, int region_type);
long BSPCountNodes(BSP_Node *tree, long node_number);
int main(int argc, char *argv[]) {
long DefaultRegionType=RegionTypeWater;
if((argc < 2) ||
(argc > 3) ||
((argc == 3)&&(strcasecmp(argv[1],"-dl")))) {
printf("Usage: %s [-dl] (zone short name) to generate a water/lava map\n\n", argv[0]);
printf(" -dl = mark special regions as lava if not tagged in .WLD\n");
printf("\nIf -dl is omitted, untagged special regions will be marked as water\n");
return(1);
}
char bufm[250];
if(argc==3)
DefaultRegionType=RegionTypeLava;
sprintf(bufm, "%s.wtr", argv[argc-1]);
if(!BuildWaterMap(argv[argc-1],DefaultRegionType))
return(1);
return(0);
}
bool BuildWaterMap(const char *shortname, long DefaultRegionType) {
// char bufm[96];
char bufs[96], bufw[96];
long WaterOrLavaCount = 0;
//TODO: clean up a LOT of memory that the freaku code does not
// sprintf(bufm, "%s.map", shortname);
sprintf(bufs, "%s.s3d", shortname);
sprintf(bufw, "%s.wld", shortname);
s3d_object s3d/*, s3d_obj, s3d_chr*/;
wld_object wld/*, wld2, wld_obj, wld_chr*/;
unsigned char *buf;
FILE *s3df = fopen(bufs, "rb");
if(s3df == NULL) {
// One day we may try EQG, but not today.
printf("Unable to open s3d file '%s'.\n", bufs);
return(false);
}
printf("Loading %s...\n", bufs);
S3D_Init(&s3d, s3df);
S3D_GetFile(&s3d, bufw, &buf);
WLD_Init(&wld, buf, &s3d, 1);
BSP_Node *tree = NULL;
struct_Data29 *data29;
for(int i=0; i<wld.fragCount; i++) {
if(wld.frags[i]->type == 0x21) {
printf("We have a type 0x21 fragment\n");
tree = (BSP_Node *) wld.frags[i]->frag;
}
if(wld.frags[i]->type == 0x29) {
printf("We have a type 0x29 fragment. ");
data29 = (struct_Data29 *) wld.frags[i]->frag;
printf("It has %ld regions and is marked as type %d. ",
data29->region_count, data29->region_type);
switch(data29->region_type) {
case RegionTypeUnsupported: { printf("Unsupported\n"); break; }
case RegionTypeUntagged: {
printf("Untagged. We will set it to ");
if(DefaultRegionType==RegionTypeWater) {
printf("Water\n");
} else printf("Lava\n");
data29->region_type = DefaultRegionType;
WaterOrLavaCount++;
break;
}
case RegionTypeWater: { printf("Water\n"); WaterOrLavaCount++; break; }
case RegionTypeLava: { printf("Lava\n"); WaterOrLavaCount++; break; }
case RegionTypeZoneLine: { printf("Zoneline\n"); break; }
default: printf("UNKNOWN\n");
}
}
}
if(tree==NULL) {
printf("No BSP Tree. Bailing out\n");
return(false);
}
if(WaterOrLavaCount==0) {
printf("No water or lava in this zone. Nothing for us to do.\n");
return(false);
}
long BSPTreeSize = BSPCountNodes(tree, 1);
printf("There are %ld nodes in the BSP tree\n", BSPTreeSize);
// Now we mark each leaf in the BSP tree that is in a 'special area' with what type the area is
// Water, Lava, Zoneline etc
for(int i=0; i<wld.fragCount; i++) {
if(wld.frags[i]->type == 0x29) {
data29 = (struct_Data29 *) wld.frags[i]->frag;
for(long j=0; j<data29->region_count; j++) {
BSPMarkRegion(tree, 1,data29->region_array[j]+1, data29->region_type);
}
}
}
// Now write out the file
char bufm[250];
sprintf(bufm, "%s.wtr", shortname);
FILE *WaterFile = fopen(bufm, "wb");
if(WaterFile == NULL) {
printf("Failed to open %s for writing\n", bufm);
return(false);
}
const char *WFMagic = "EQEMUWATER";
const long WFVersion = 1;
if(fwrite(WFMagic, strlen(WFMagic), 1, WaterFile) != 1) {
printf("Error writing output file\n");
fclose(WaterFile);
return(false);
}
if(fwrite(&WFVersion, sizeof(WFVersion), 1, WaterFile) != 1) {
printf("Error writing output file\n");
fclose(WaterFile);
return(false);
}
if(fwrite(&BSPTreeSize, sizeof(BSPTreeSize), 1, WaterFile) != 1) {
printf("Error writing output file\n");
fclose(WaterFile);
return(false);
}
if(fwrite(tree, sizeof(BSP_Node), BSPTreeSize, WaterFile) != BSPTreeSize) {
printf("Error writing output file\n");
fclose(WaterFile);
return(false);
}
fclose(WaterFile);
return(true);
}
void PrintBSP(BSP_Node *tree, long node_number) {
printf("Node %ld, Left=%ld, Right=%ld\n",
node_number-1,
tree[node_number-1].left,
tree[node_number-1].right);
printf("Normals are %4.3f, %4.3f, %4.3f, SplitD is %4.3f\n",
tree[node_number-1].normal[0],
tree[node_number-1].normal[1],
tree[node_number-1].normal[2],
tree[node_number-1].splitdistance);
if(tree[node_number-1].left!=0) PrintBSP(tree, tree[node_number-1].left);
if(tree[node_number-1].right!=0) PrintBSP(tree, tree[node_number-1].right);
if((tree[node_number-1].left==0)&&
(tree[node_number-1].right==0)) {
printf("Region pointer is %ld\n", tree[node_number-1].region);
}
}
long BSPCountNodes(BSP_Node *tree, long node_number) {
long NodesInRightBranch = 0, NodesInLeftBranch = 0;
if((tree[node_number-1].left==0)&&
(tree[node_number-1].right==0)) return 1;
if(tree[node_number-1].left!=0) NodesInLeftBranch = BSPCountNodes(tree, (tree[node_number-1].left));
if(tree[node_number-1].right!=0) NodesInRightBranch = BSPCountNodes(tree, (tree[node_number-1].right));
return(NodesInRightBranch + NodesInLeftBranch + 1);
}
long BSPFindRegion(BSP_Node *tree, long node_number, long region) {
//printf("Find Region %ld in node %ld\n", region, node_number);
if(node_number<1) {
printf("Something went wrong\n");
exit(1);
}
if((tree[node_number-1].left==0)&&
(tree[node_number-1].right==0)) {
if(tree[node_number-1].region==region) return node_number;
}
long retnode ;
if(tree[node_number-1].left!=0) {
retnode = BSPFindRegion(tree, tree[node_number-1].left, region);
if(retnode != 0) return retnode ;
}
if(tree[node_number-1].right!=0) {
return BSPFindRegion(tree, tree[node_number-1].right, region);
}
return 0;
}
long BSPFindNode(BSP_Node *tree, long node_number, float x, float y, float z) {
float distance;
printf("BSP Find Node, currently in Node %ld\n", node_number);
// Are we at a leaf
if((tree[node_number-1].left==0)&&
(tree[node_number-1].right==0)) {
return tree[node_number-1].region;
}
// No, so determine which side of the split plane we are on
//
distance = (x * tree[node_number-1].normal[0]) +
(y * tree[node_number-1].normal[1]) +
(z * tree[node_number-1].normal[2]) +
tree[node_number-1].splitdistance;
printf("Distance is %4.3f\n", distance);
// Guess which side to go down
if(distance == 0.0f) {
printf("Distance is 0, don't know what to do!\n");
exit(1);
}
if(distance >0.0f) {
if(tree[node_number-1].left==0) {
printf("Pos and no left node, abort!\n");
exit(1);
}
return BSPFindNode(tree, tree[node_number-1].left,
x, y, z);
}
if(tree[node_number-1].right==0) {
printf("Neg and no right node, abort!\n");
exit(1);
}
return BSPFindNode(tree, tree[node_number-1].right,
x, y, z);
}
long BSPMarkRegion(BSP_Node *tree, long node_number, long region, int region_type) {
//printf("Find Region %ld in node %ld\n", region, node_number);
if(node_number<1) {
printf("Something went wrong\n");
exit(1);
}
if((tree[node_number-1].left==0)&&
(tree[node_number-1].right==0)) {
if(tree[node_number-1].region==region) {
tree[node_number-1].special=region_type;
return node_number;
}
}
long retnode ;
if(tree[node_number-1].left!=0) {
retnode = BSPMarkRegion(tree, tree[node_number-1].left, region, region_type);
if(retnode != 0) return retnode ;
}
if(tree[node_number-1].right!=0) {
return BSPMarkRegion(tree, tree[node_number-1].right, region, region_type);
}
return 0;
}
+10
View File
@@ -0,0 +1,10 @@
typedef enum {
RegionTypeUnsupported = -2,
RegionTypeUntagged = -1,
RegionTypeNormal = 0,
RegionTypeWater = 1,
RegionTypeLava = 2,
RegionTypeZoneLine = 3
} WaterRegionType;
File diff suppressed because it is too large Load Diff
+192
View File
@@ -0,0 +1,192 @@
#ifndef AZONE_H
#define AZONE_H
//pull in datatypes from zone's map.h
#include "../../zone/map.h"
/*
Father Nitwit's zone to map file converter.
*/
#include <stdio.h>
#include <vector>
#include <map>
using namespace std;
#define COUNT_MACTHES 1
//this is the version number to put in the map header
#undef MAP_VERSION //override this from map.h with our version
#define MAP_VERSION 0x01000000
//quadtree stopping criteria, comment any to disable them
#define MAX_QUADRENT_FACES 50 //if box has fewer than this, stop
#define MIN_QUADRENT_SIZE 100.0f //if box has a dimention smaller than this, stop
#define MIN_QUADRENT_GAIN 0.3f //minimum split ratio before stopping
#define MAX_QUADRENT_MISSES 2 //maximum number of quads which can miss their gains
//1 or 2 make sense, others are less useful
//attepmt to trim the data a little
#define MAX_Z 3000.0 //seems to be a lot of points above this
//if all points on poly are, kill it.
/*
This is used for the recursive node structure
unsigned shorts are adequate because, worst case
even in a zone that is 6000x6000 with a small node
size of 30x30, there are only 40000 nodes.
quadrent definitions:
quad 1 (nodes[0]):
x>=0, y>=0
quad 2 (nodes[1]):
x<0, y>=0
quad 3 (nodes[2]):
x<0, y<0
quad 4 (nodes[3]):
x>=0, y<0
*/
#define MAX_POLY_VTX 24 //arbitrary, im too lazy to figure it out
//cut a triangle at most 6 times....
struct POLYGON {
VERTEX /*w[MAX_POLY_VTX], */c[MAX_POLY_VTX];
int count; // w is world points, c is for camera points
};
class GPoint {
public:
GPoint();
GPoint(VERTEX &v);
GPoint(float x, float y, float z);
inline void operator()(float nx, float ny, float nz) { x = nx; y = ny; z = nz; }
GPoint cross(const GPoint &them) const;
float dot3(const GPoint &them) const;
float x;
float y;
float z;
};
GPoint operator-(const GPoint &v1, const GPoint &v2);
class GVector : public GPoint {
public:
GVector();
GVector(const GPoint &them);
GVector(float x, float y, float z, float w = 1.0f);
inline void operator()(float nx, float ny, float nz, float nw) { x = nx; y = ny; z = nz; W = nw; }
float dot4(const GVector &them) const;
float dot4(const GPoint &them) const;
void normalize();
float length();
float W;
};
struct FaceRecord {
FACE *face;
unsigned long index;
};
class QTNode;
class QTBuilder {
public:
QTBuilder();
~QTBuilder();
bool build(const char *shortname);
bool build_eqg(const char *shortname);
bool writeMap(const char *file);
bool FaceInNode(const QTNode *q, const FACE *f);
protected:
void AddFace(VERTEX &v1, VERTEX &v2, VERTEX &v3);
int ClipPolygon(POLYGON *poly, GVector *plane);
//dynamic during load
// vector<VERTEX> _VertexList;
vector<FACE> _FaceList;
//static once loaded
// unsigned long vertexCount;
unsigned long faceCount;
// VERTEX * vertexBlock;
FACE * faceBlock;
VERTEX tempvtx[MAX_POLY_VTX];
QTNode *_root;
static void NormalizeN(FACE *p);
#ifdef COUNT_MACTHES
unsigned long gEasyMatches;
unsigned long gEasyExcludes;
unsigned long gHardMatches;
unsigned long gHardExcludes;
#endif
};
//quadtree node container
class QTNode {
public:
QTNode(QTBuilder *builder, float Tminx, float Tmaxx, float Tminy, float Tmaxy);
~QTNode();
void clearNodes();
void doSplit();
void divideYourself(int depth);
void buildVertexes();
// bool writeFile(FILE *out);
unsigned long countNodes() const;
unsigned long countFacelists() const;
void fillBlocks(nodeHeader *heads, unsigned long *flist, unsigned long &hindex, unsigned long &findex);
float minx;
float miny;
float maxx;
float maxy;
unsigned long nfaces;
vector<FaceRecord> faces;
/*
quadrent definitions:
quad 1 (node1):
x>=0, y>=0
quad 2 (node2):
x<0, y>=0
quad 3 (node3):
x<0, y<0
quad 4 (node4):
x>=0, y<0
*/
QTNode *node1;
QTNode *node2;
QTNode *node3;
QTNode *node4;
GPoint v[8];
bool final;
protected:
QTBuilder *builder;
};
#endif
+31
View File
@@ -0,0 +1,31 @@
#include <stdio.h>
#include <string.h>
#include "file.hpp"
int GetFile(uchar **buffer, int *buf_len, char *base_path, char *file_name, Archive *archive) {
FILE *fp;
char *temp;
if(base_path) {
temp = new char[strlen(base_path) + strlen(file_name) + 2];
sprintf(temp, "%s/%s", base_path, file_name);
fp = fopen(temp, "rb");
delete[] temp;
if(!fp)
return 0;
fseek(fp, 0, SEEK_END);
*buf_len = ftell(fp);
fseek(fp, 0, SEEK_SET);
*buffer = new uchar[*buf_len];
fread(*buffer, 1, *buf_len, fp);
fclose(fp);
return 1;
}
else
return archive->GetFile(file_name, buffer, buf_len);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef __OPENEQ_FILE__
#define __OPENEQ_FILE__
#include "archive.hpp"
int GetFile(uchar **buffer, int *buf_len, char *base_path, char *file_name, Archive *archive);
#endif
+24
View File
@@ -0,0 +1,24 @@
#ifndef __OPENEQ_FL_API__
#define __OPENEQ_FL_API__
#include "archive.hpp"
#include "3d.hpp"
class FileLoader {
public:
FileLoader() {}
virtual ~FileLoader() {}
virtual int Open(char *base_path, char *zone_name, Archive *archive) = 0;
virtual int Close() = 0;
Content_3D model_data;
protected:
uchar *buffer;
int buf_len;
Archive *archive;
int status;
};
#endif
+24
View File
@@ -0,0 +1,24 @@
#ifndef __OPENEQ_GLOBALS__
#define __OPENEQ_GLOBALS__
#ifdef WIN32
//#include <winsock.h>
#else
#include <netinet/in.h>
#endif
#ifndef NULL
#define NULL 0
#endif
typedef unsigned long uint32;
typedef long int32;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned char uint8;
typedef unsigned char uchar;
typedef char int8;
#endif
+43
View File
@@ -0,0 +1,43 @@
#ifndef __OPENEQ_OCTREE__
#define __OPENEQ_OCTREE__
#ifdef WIN32
#define Polygon Polygon_win32
#include <windows.h>
#undef Polygon
#endif
#include "3d_base.hpp"
class Octree_Node {
public:
Octree_Node();
Octree_Node(int poly_count, Polygon **polys, Vertex **verts, int plac_count, Placeable **plac);
Octree_Node(int poly_count, Polygon **polys, Vertex **verts, int plac_count, Placeable **plac, float min[3], float max[3]);
~Octree_Node();
void FindMinMax();
void Split(char level);
float min[3], max[3];
float x, y, z, size, sizes[3];
int poly_count;
Vertex **verts;
Polygon **polys;
int plac_count;
Placeable **plac;
GLuint li;
Octree_Node *nodes[8];
};
#define in_box(obj, x, y, z) \
( \
(x) >= (obj)->min[0] && (x) <= (obj)->max[0] && \
(y) >= (obj)->min[1] && (y) <= (obj)->max[1] &&\
(z) >= (obj)->min[2] && (z) <= (obj)->max[2] \
)
#endif
+222
View File
@@ -0,0 +1,222 @@
#include <string.h>
#include <zlib.h>
#include "pfs.hpp"
#ifdef WIN32
#include <winsock.h>
#endif
#pragma pack(1)
struct struct_header {
uint32 offset;
char magicCookie[4];
uint32 unknown;
} typedef struct_header;
struct struct_directory_header {
uint32 count;
} typedef struct_directory_header;
struct struct_directory {
uint32 crc, offset, size;
} typedef struct_directory;
struct struct_data_block {
uint32 deflen, inflen;
} typedef struct_data_block;
struct struct_fn_header {
uint32 fncount;
} typedef struct_fn_header;
struct struct_fn_entry {
uint32 fnlen;
} typedef struct_fn_entry;
#pragma pack()
inline void decompress(char *p, char *p2, int len, int uLen) {
int status;
z_stream d_stream;
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = (Bytef *) p;
d_stream.avail_in = len;
d_stream.next_out = (Bytef *) p2;
d_stream.avail_out = uLen;
inflateInit(&d_stream);
status = inflate(&d_stream, Z_NO_FLUSH);
inflateEnd(&d_stream);
}
inline void Lower(char *str) {
while(*str) {
if(*str >= 'A' && *str <= 'Z')
*str += 'a' - 'A';
++str;
}
}
PFSLoader::PFSLoader() {
// Set the status of the loader that nothing is loaded.
this->buffer = NULL;
this->buf_len = -1;
this->status = 0;
}
PFSLoader::~PFSLoader() {
this->Close();
}
int PFSLoader::Open(FILE *fp) {
struct_header s3d_header;
struct_directory_header s3d_dir_header;
struct_directory s3d_dir;
struct_data_block s3d_data;
struct_fn_header *s3d_fn_header;
struct_fn_entry *s3d_fn_entry;
uint32 *offsets;
char *temp, *temp2;
int i, j, pos, inf, tmp, running = 0;
fread(&s3d_header, sizeof(struct_header), 1, fp);
if(s3d_header.magicCookie[0] != 'P' || s3d_header.magicCookie[1] != 'F' || s3d_header.magicCookie[2] != 'S' || s3d_header.magicCookie[3] != ' ')
return 0;
this->fp = fp;
fseek(fp, s3d_header.offset, SEEK_SET);
fread(&s3d_dir_header, sizeof(struct_directory_header), 1, fp);
this->count = s3d_dir_header.count - 1;
this->filenames = new char *[s3d_dir_header.count];
this->files = new uint32[s3d_dir_header.count - 1];
offsets = new uint32[s3d_dir_header.count - 1];
for(i = 0; i < (int)s3d_dir_header.count; ++i) {
fread(&s3d_dir, sizeof(struct_directory), 1, fp);
if(s3d_dir.crc == ntohl(0xC90A5861)) {
pos = ftell(fp);
fseek(fp, s3d_dir.offset, SEEK_SET);
temp = new char[s3d_dir.size];
memset(temp, 0, s3d_dir.size);
inf = 0;
while(inf < (int)s3d_dir.size) {
fread(&s3d_data, sizeof(struct_data_block), 1, fp);
temp2 = new char[s3d_data.deflen];
fread(temp2, s3d_data.deflen, 1, fp);
decompress(temp2, temp + inf, s3d_data.deflen, s3d_data.inflen);
delete[] temp2;
inf += s3d_data.inflen;
}
fseek(fp, pos, SEEK_SET);
s3d_fn_header = (struct_fn_header *) temp;
pos = sizeof(struct_fn_header);
for(j = 0; j < (int)s3d_fn_header->fncount; ++j) {
s3d_fn_entry = (struct_fn_entry *) &temp[pos];
this->filenames[j] = new char[s3d_fn_entry->fnlen + 1];
this->filenames[j][s3d_fn_entry->fnlen] = 0;
memcpy(this->filenames[j], &temp[pos + sizeof(struct_fn_entry)], s3d_fn_entry->fnlen);
pos += sizeof(struct_fn_entry) + s3d_fn_entry->fnlen;
}
}
else {
this->files[running] = ftell(fp) - 12;
offsets[running] = s3d_dir.offset;
++running;
}
}
for(i = s3d_dir_header.count - 2; i > 0; i--) {
for(j = 0; j < i; j++) {
if(offsets[j] > offsets[j+1]) {
tmp = offsets[j];
offsets[j] = offsets[j + 1];
offsets[j + 1] = tmp;
tmp = this->files[j];
this->files[j] = this->files[j + 1];
this->files[j + 1] = tmp;
}
}
}
return 1;
}
int PFSLoader::Close() {
if(this->status) {
while(this->count > 0) {
delete this->filenames[this->count - 1];
--this->count;
}
delete[] this->filenames;
delete[] this->files;
}
else
return 0;
this->buffer = NULL;
this->buf_len = -1;
this->status = 0;
return 1;
}
const char *PFSLoader::FindExtension(const char *ext) {
int i;
int elen = strlen(ext);
for(i = 0; i < this->count; ++i) {
//printf("Look for %s: got %s\n", ext, this->filenames[i]);
int flen = strlen(this->filenames[i]);
if(flen <= elen)
continue;
if(!strcmp(this->filenames[i]+(flen-elen), ext))
return(this->filenames[i]);
}
return(NULL);
}
int PFSLoader::GetFile(char *name, uchar **buf, int *len) {
struct_directory s3d_dir;
struct_data_block s3d_data;
char *temp2;
long inf;
int i;
Lower(name);
for(i = 0; i < this->count; ++i) {
//printf("Look for %s: got %s\n", name, this->filenames[i]);
if(!strcmp(this->filenames[i], name)) {
fseek(this->fp, this->files[i], SEEK_SET);
fread(&s3d_dir, sizeof(struct_directory), 1, this->fp);
fseek(this->fp, s3d_dir.offset, SEEK_SET);
*buf = new uchar[s3d_dir.size];
inf = 0;
while(inf < (int)s3d_dir.size) {
fread(&s3d_data, sizeof(struct_data_block), 1, this->fp);
temp2 = new char[s3d_data.deflen];
fread(temp2, s3d_data.deflen, 1, this->fp);
decompress(temp2, (char *) *buf + inf, s3d_data.deflen, s3d_data.inflen);
delete[] temp2;
inf += s3d_data.inflen;
}
*len = inf;
return 1;
}
}
return 0;
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef __OPENEQ_PFS__
#define __OPENEQ_PFS__
#include <stdio.h>
#include "global.hpp"
#include "archive.hpp"
class PFSLoader : public Archive {
public:
PFSLoader();
~PFSLoader();
virtual int Open(FILE *fp);
virtual int Close();
virtual int GetFile(char *name, uchar **buf, int *len);
virtual const char *FindExtension(const char *ext);
};
#endif
+136
View File
@@ -0,0 +1,136 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include "s3d.h"
void decompress(char *p, char *p2, int len, int uLen) {
int status;
z_stream d_stream;
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = p;
d_stream.avail_in = len;
d_stream.next_out = p2;
d_stream.avail_out = uLen;
inflateInit(&d_stream);
status = inflate(&d_stream, Z_NO_FLUSH);
inflateEnd(&d_stream);
}
int S3D_Init(s3d_object *obj, FILE *fp) {
struct_header s3d_header;
struct_directory_header s3d_dir_header;
struct_directory s3d_dir;
struct_data_block s3d_data;
struct_fn_header *s3d_fn_header;
struct_fn_entry *s3d_fn_entry;
uint32 *offsets;
char *temp, *temp2;
int i, j, pos, inf, tmp, running = 0;
obj->fp = fp;
fread(&s3d_header, sizeof(struct_header), 1, fp);
if(s3d_header.magicCookie[0] != 'P' || s3d_header.magicCookie[1] != 'F' || s3d_header.magicCookie[2] != 'S' || s3d_header.magicCookie[3] != ' ')
return -1;
fseek(fp, s3d_header.offset, SEEK_SET);
fread(&s3d_dir_header, sizeof(struct_directory_header), 1, fp);
obj->count = s3d_dir_header.count;
obj->filenames = (char **) malloc(s3d_dir_header.count * sizeof(char *));
obj->files = (uint32 *) malloc((s3d_dir_header.count - 1) * sizeof(uint32));
offsets = (uint32 *) malloc((s3d_dir_header.count - 1) * sizeof(uint32));
for(i = 0; i < s3d_dir_header.count; ++i) {
fread(&s3d_dir, sizeof(struct_directory), 1, fp);
if(s3d_dir.crc == 0x61580AC9) {
pos = ftell(fp);
fseek(fp, s3d_dir.offset, SEEK_SET);
temp = (char *) malloc(s3d_dir.size);
memset(temp, 0, s3d_dir.size);
inf = 0;
while(inf < s3d_dir.size) {
fread(&s3d_data, sizeof(struct_data_block), 1, fp);
temp2 = (char *) malloc(s3d_data.deflen);
fread(temp2, s3d_data.deflen, 1, fp);
decompress(temp2, temp + inf, s3d_data.deflen, s3d_data.inflen);
free(temp2);
inf += s3d_data.inflen;
}
fseek(fp, pos, SEEK_SET);
s3d_fn_header = (struct_fn_header *) temp;
pos = sizeof(struct_fn_header);
for(j = 0; j < s3d_fn_header->fncount; ++j) {
s3d_fn_entry = (struct_fn_entry *) &temp[pos];
obj->filenames[j] = (char *) malloc(s3d_fn_entry->fnlen + 1);
obj->filenames[j][s3d_fn_entry->fnlen] = 0;
memcpy(obj->filenames[j], &temp[pos + sizeof(struct_fn_entry)], s3d_fn_entry->fnlen);
pos += sizeof(struct_fn_entry) + s3d_fn_entry->fnlen;
}
}
else {
obj->files[running] = ftell(fp) - 12;
offsets[running] = s3d_dir.offset;
++running;
}
}
for(i = s3d_dir_header.count - 2; i > 0; i--) {
for(j = 0; j < i; j++) {
if(offsets[j] > offsets[j+1]) {
tmp = offsets[j];
offsets[j] = offsets[j + 1];
offsets[j + 1] = tmp;
tmp = obj->files[j];
obj->files[j] = obj->files[j + 1];
obj->files[j + 1] = tmp;
}
}
}
return 0;
}
size_t S3D_GetFile(s3d_object *obj, char *filename, uchar **out) {
struct_directory s3d_dir;
struct_data_block s3d_data;
uchar *buf;
char *temp2;
long inf;
int i;
for(i = 0; i < obj->count; ++i) {
if(!strcmp(obj->filenames[i], filename)) {
fseek(obj->fp, obj->files[i], SEEK_SET);
fread(&s3d_dir, sizeof(struct_directory), 1, obj->fp);
fseek(obj->fp, s3d_dir.offset, SEEK_SET);
buf = (uchar *) malloc(s3d_dir.size);
inf = 0;
while(inf < s3d_dir.size) {
fread(&s3d_data, sizeof(struct_data_block), 1, obj->fp);
temp2 = (char *) malloc(s3d_data.deflen);
fread(temp2, s3d_data.deflen, 1, obj->fp);
decompress(temp2, (char *) buf + inf, s3d_data.deflen, s3d_data.inflen);
free(temp2);
inf += s3d_data.inflen;
}
*out = buf;
return inf;
}
}
return -1;
}
+51
View File
@@ -0,0 +1,51 @@
#ifndef __EQCLIENT_S3D_H_
#define __EQCLIENT_S3D_H_
#include <stdio.h>
#include "types.h"
typedef struct struct_header {
uint32 offset;
char magicCookie[4];
uint32 unknown;
} struct_header;
typedef struct struct_directory_header {
uint32 count;
} struct_directory_header;
typedef struct struct_directory {
uint32 crc, offset, size;
} struct_directory;
typedef struct struct_data_block {
uint32 deflen, inflen;
} struct_data_block;
typedef struct struct_fn_header {
uint32 fncount;
} struct_fn_header;
typedef struct struct_fn_entry {
uint32 fnlen;
} struct_fn_entry;
typedef struct s3d_object {
FILE *fp;
long count;
char **filenames;
uint32 *files;
} s3d_object;
#ifdef __cplusplus
extern "C" {
#endif
int S3D_Init(s3d_object *obj, FILE *fp);
size_t S3D_GetFile(s3d_object *obj, char *filename, uchar **out);
#ifdef __cplusplus
}
#endif
#endif
+413
View File
@@ -0,0 +1,413 @@
#include <stdio.h>
#ifdef WIN32 //vc++ chokes here without this
#include <string>
#else
#include <string.h>
#endif
#include <stdlib.h>
#include <iostream>
#include "file.hpp"
#include "ter.hpp"
using namespace std;
TERLoader::TERLoader() {
this->buffer = NULL;
this->buf_len = -1;
this->archive = NULL;
this->status = 0;
}
TERLoader::~TERLoader() {
this->Close();
}
void build_hex_line(const char *buffer, unsigned long length, unsigned long offset, char *out_buffer, unsigned char padding)
{
char *ptr=out_buffer;
int i;
char printable[17];
ptr+=sprintf(ptr,"%0*i:",padding,offset);
for(i=0;i<16; i++) {
if (i==8) {
strcpy(ptr," -");
ptr+=2;
}
if (i+offset < length) {
unsigned char c=*(const unsigned char *)(buffer+offset+i);
ptr+=sprintf(ptr," %02x",c);
printable[i]=isprint(c) ? c : '.';
} else {
ptr+=sprintf(ptr," ");
printable[i]=0;
}
}
sprintf(ptr," | %.16s",printable);
}
void print_hex(const char *data, unsigned long length) {
char buffer[80];
uint32 offset;
for(offset=0;offset<length;offset+=16) {
build_hex_line(data,length,offset,buffer,5);
printf("%s\n", buffer); //%s is to prevent % escapes in the ascii
}
}
int TERLoader::Open(char *base_path, char *zone_name, Archive *archive) {
ter_header *thdr;
ter_vertex *tver;
ter_vertex_v3 *tver3;
ter_triangle *ttri;
uchar *ter_orig, *ter_tmp;
int model = 0;
int i, j, mat_count = 0;
Zone_Model *zm;
material *mlist;
char var_len, val_len;
char *var, *val;
uchar *buffer;
int buf_len, bone_count;
char *filename;
if(zone_name[strlen(zone_name) - 4] == '.')
filename = zone_name;
else {
filename = new char[strlen(zone_name) + 5];
sprintf(filename, "%s.ter", zone_name);
}
if(!GetFile(&buffer, &buf_len, base_path, filename, archive)) {
if(filename != zone_name)
delete[] filename;
return 0;
}
printf("Writting TER to '%s'\n", filename);
FILE *ttt = fopen(filename, "wb");
fwrite(buffer, 1, buf_len, ttt);
fclose(ttt);
if(filename != zone_name)
delete[] filename;
thdr = (ter_header *) buffer;
mlist = new material[thdr->mat_count];
ter_orig = buffer;
if(thdr->magic[0] != 'E' || thdr->magic[1] != 'Q' || thdr->magic[2] != 'G')
return 0;
if(thdr->magic[3] == 'M') {
printf("Model File encountered in TER loader!\n");
return(0);
}
else if(thdr->magic[3] == 'T') {
buffer += sizeof(ter_header);
} else
return 0;
ter_tmp = buffer + thdr->list_len;
if(thdr->version == 3)
{
if(sizeof(ter_header) + thdr->list_len + (thdr->vert_count * sizeof(ter_vertex_v3)) + (thdr->tri_count * sizeof(ter_triangle)) > (unsigned int)buf_len)
{
printf("Buffer Range Check Failed.\n");
return 0;
}
}
else
{
if(sizeof(ter_header) + thdr->list_len + (thdr->vert_count * sizeof(ter_vertex)) + (thdr->tri_count * sizeof(ter_triangle)) > (unsigned int)buf_len)
{
printf("Buffer Range Check Failed(v3).\n");
return 0;
}
}
for(i = 0; i < (int)thdr->mat_count; ++i) {
mlist[i].name = NULL;
mlist[i].basetex = NULL;
}
int line_count = 0;
j = 0;
while(buffer < ter_tmp) {
val_len = strlen((char *) buffer);
val = (char *) buffer;
buffer += val_len + 1;
var_len = strlen((char *) buffer);
var = (char *) buffer;
line_count++;
// printf("%s %s\n", val, var);
if(strlen(var) == 0 || strlen(val) == 0) {
++buffer;
continue;
}
if(!strcmp(val, "e_fShininess0")) {
// Shiny!
continue;
}
else if(!strcmp(var, "e_TextureDiffuse0")) {
mlist[j].basetex = new char[val_len + 1];
memcpy(mlist[j].basetex, val, val_len + 1);
++mat_count;
// printf("%i: Basetex: %s\n", j + 1, mlist[j].basetex);
++j;
}
else if(val[0] != 'e' && val[1] != '_' && ((var[0] != 'e' && var[1] != '_') || !strcmp(val, "e_fShininess0"))) {
if(val[val_len - 3] == '.') {
mlist[j].name = new char[var_len + 1];
memcpy(mlist[j].name, var, var_len + 1);
}
else {
mlist[j].name = new char[val_len + 1];
memcpy(mlist[j].name, val, val_len + 1);
continue;
}
// printf("Named: %s\n", mlist[j].name);
}
buffer += var_len + 1;
}
printf("%s: Material count: %d, list len=%d, line count=%d\n", zone_name, thdr->mat_count, thdr->list_len, line_count);
this->model_data.zone_model = new Zone_Model;
zm = this->model_data.zone_model;
zm->vert_count = thdr->vert_count;
zm->poly_count = thdr->tri_count;
zm->verts = new Vertex *[zm->vert_count];
zm->polys = new Polygon *[zm->poly_count];
this->model_data.plac_count = 0;
this->model_data.model_count = 0;
//this is not always correct!
// Derision. Fix offset calculation for EQG version 2
//
//#define DEBUGTER
buffer = ter_orig + thdr->list_len + sizeof(ter_header);
if(thdr->magic[3] == 'M') buffer = buffer + 4;
#ifdef DEBUGTER
printf("Starting offset is %8X\n", buffer-ter_orig);
#endif
for(int b=0; b<thdr->mat_count; b++) {
unsigned long property_count = *((unsigned long *)(buffer+12));
#ifdef DEBUGTER
printf("Property count is %d\n", property_count); fflush(stdout);
#endif
buffer += 16;
for (int a=0; a<property_count; a++)
buffer += 12;
}
#ifdef DEBUGTER
printf("Offset is %8X\n", buffer - ter_orig);
#endif
printf("Orig Delta %d 0x%x\n", buffer-ter_tmp, buffer-ter_tmp);
/*
* This is the biggest hack pile of crap ever... but I am tired of trying to
* figure out this file format, so im just looking at the files for the offsets
* myself.
*
*/
/*if(string("ter_broodlands.ter") == zone_name) {
buffer = ter_orig + 0x382BB - 4;
// zm->vert_count = (0x2ABF90-0x382BB-4)/sizeof(ter_vertex);
} else if(string("ter_volcano.ter") == zone_name) {
if(thdr->mat_count == 19320) {
buffer = ter_orig + 0x39BB66;
} else {
buffer = ter_orig + 0x38BF0;
}
} else if(string("ter_guildhall.ter") == zone_name) {
buffer = ter_orig + 0x3080 - 2;
} else if(string("ter_guildlobby.ter") == zone_name) {
buffer = ter_orig + 0x4190 + 19;
} else if(string("ter_harbingers.ter") == zone_name) {
buffer = ter_orig + 0x1178;
} else if(string("ter_main.ter") == zone_name) {
//stillmoona
buffer = ter_orig + 0x71944+4;
} else if(string("ter_easterntemple.ter") == zone_name) {
//stillmoonb
buffer = ter_orig + 0xE340-2;
} else if(string("ter_abyss01.ter") == zone_name) {
//thenest
buffer = ter_orig + 0xCA244;
} else if(string("ter_stormtower01.ter") == zone_name) {
//thundercrest
buffer = ter_orig + 0x62230-4;
}*/
/* buffer = ter_orig + 0x382BB - 4;
printf("Good Delta %d 0x%x\n", buffer-ter_tmp, buffer-ter_tmp);*/
/*
uchar *pptr2 = (buffer - (sizeof(ter_vertex)*1));
printf("v dump start: 0x%x\n", (pptr2-ter_orig));
print_hex((const char *)pptr2, (buffer-pptr2)+sizeof(ter_vertex)*10);
*/
printf("%d verts start at %d (0x%x)\n", zm->vert_count, (buffer-ter_orig), (buffer-ter_orig));
print_hex((const char *)(buffer-16), sizeof(ter_vertex)*3+16);
for(i = 0; i < zm->vert_count; ++i) {
if(thdr->version == 3)
{
tver3 = (ter_vertex_v3 *) buffer;
zm->verts[i] = new Vertex;
zm->verts[i]->x = tver3->x;
zm->verts[i]->y = tver3->y;
zm->verts[i]->z = tver3->z;
zm->verts[i]->u = tver3->u;
zm->verts[i]->v = tver3->v;
buffer += sizeof(ter_vertex_v3);
}
else
{
tver = (ter_vertex *) buffer;
zm->verts[i] = new Vertex;
zm->verts[i]->x = tver->x;
zm->verts[i]->y = tver->y;
zm->verts[i]->z = tver->z;
zm->verts[i]->u = tver->u;
zm->verts[i]->v = tver->v;
buffer += sizeof(ter_vertex);
}
}
/* uchar *pptr = (buffer);
printf("dump tri start: 0x%x\n", (pptr-ter_orig));
print_hex((const char *)(pptr-16), 16+sizeof(ter_triangle)*10);
int skipped = 0;
j = 0;
printf("%d tris start at %d (0x%x)\n", zm->poly_count, (buffer-ter_orig), (buffer-ter_orig));*/
printf("dump tri start: 0x%x\n", (buffer));
print_hex((const char *)(buffer-16), 16+sizeof(ter_triangle)*10);
printf("%d tris start at %d (0x%x)\n", zm->poly_count, (buffer), (buffer));
uint8 errored = 0;
int skipped = 0;
j = 0;
for(i = 0; i < zm->poly_count; ++i) {
ttri = (ter_triangle *) buffer;
if(ttri->group == -1) {
skipped++;
buffer += sizeof(ter_triangle);
continue;
}
zm->polys[j] = new Polygon;
//printf(" v1=%d, v2=%d, v3=%d, g=%d, unk=%d\n", ttri->v1, ttri->v2, ttri->v3, ttri->group, ttri->unk);
if(ttri->v1 >= zm->vert_count && errored < 10) {
printf("Tri %d/%d (s %d) @0x%x: invalid v1: %d >= %d\n", i, zm->poly_count, skipped, (buffer-ter_orig), ttri->v1, zm->vert_count);
errored++;
}
if(ttri->v2 >= zm->vert_count && errored < 10) {
printf("Tri %d/%d (s %d) @0x%x: invalid v2: %d >= %d\n", i, zm->poly_count, skipped, (buffer-ter_orig), ttri->v2, zm->vert_count);
errored++;
}
if(ttri->v3 >= zm->vert_count && errored < 10) {
printf("Tri %d/%d (s %d) @0x%x: invalid v3: %d >= %d\n", i, zm->poly_count, skipped, (buffer-ter_orig), ttri->v3, zm->vert_count);
errored++;
}
if(ttri->v1 == 0x80000 && ttri->v1 >= zm->vert_count) {
zm->polys[j]->v1 = 0;
zm->polys[j]->v2 = 0;
zm->polys[j]->v3 = 0;
} else {
zm->polys[j]->v1 = ttri->v1;
zm->polys[j]->v2 = ttri->v2;
zm->polys[j]->v3 = ttri->v3;
if(ttri->group == -1)
zm->polys[j]->tex = thdr->mat_count;
else
zm->polys[j]->tex = ttri->group;
}
++j;
buffer += sizeof(ter_triangle);
}
printf("Skipped %d, %d total\n", skipped, zm->poly_count);
zm->poly_count = j;
zm->tex_count = thdr->mat_count;
zm->tex = new Texture *[thdr->mat_count];
for(i = 0; i < (int)thdr->mat_count; ++i) {
zm->tex[i] = new Texture;
zm->tex[i]->frame_count = 1;
zm->tex[i]->filenames = new char *[1];
if(mlist[i].basetex) {
zm->tex[i]->filenames[0] = new char[strlen(mlist[i].basetex) + 1];
memcpy(zm->tex[i]->filenames[0], mlist[i].basetex, strlen(mlist[i].basetex) + 1);
delete[] mlist[i].basetex;
}
else if(mlist[i].name) {
zm->tex[i]->filenames[0] = new char[strlen(mlist[i].name) + 1];
memcpy(zm->tex[i]->filenames[0], mlist[i].name, strlen(mlist[i].name) + 1);
delete[] mlist[i].name;
}
}
// zm->tex[thdr->mat_count] = new Texture;
// zm->tex[thdr->mat_count]->filename = NULL;
delete[] mlist;
this->status = 1;
return 1;
}
int TERLoader::Close() {
Zone_Model *zm = this->model_data.zone_model;
int i;
if(!this->status)
return 1;
for(i = 0; i < zm->vert_count; ++i)
delete zm->verts[i];
for(i = 0; i < zm->poly_count; ++i)
delete zm->polys[i];
for(i = 0; i < zm->tex_count; ++i) {
delete[] zm->tex[i]->filenames[0];
delete[] zm->tex[i]->filenames;
delete zm->tex[i];
}
delete[] zm->verts;
delete[] zm->polys;
delete this->model_data.zone_model;
return 1;
}
+51
View File
@@ -0,0 +1,51 @@
#ifndef __OPENEQ_TER__
#define __OPENEQ_TER__
#include "global.hpp"
#include "file_loader.hpp"
#pragma pack(1)
struct ter_header {
char magic[4];
unsigned long version, list_len, mat_count, vert_count, tri_count;
} typedef ter_header;
struct ter_vertex {
float x, y, z;
float i, j, k;
float u, v;
} typedef ter_vertex;
struct ter_triangle {
long v1, v2, v3;
long group;
long unk;
} typedef ter_triangle;
struct ter_vertex_v3 {
float x, y, z;
float i, j, k;
float unk1, unk2, unk3;
float u, v;
} typedef ter_vertex_v3;
struct material {
char *name;
char *basetex;
char var_count;
char **var_names;
char **var_vals;
} typedef material;
#pragma pack()
class TERLoader : public FileLoader {
public:
TERLoader();
~TERLoader();
virtual int Open(char *base_path, char *zone_name, Archive *archive);
virtual int Close();
};
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef __EQCLIENT_TYPES_H_
#define __EQCLIENT_TYPES_H_
typedef unsigned long uint32;
typedef long int32;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned char uint8;
typedef unsigned char uchar;
typedef char int8;
#define null 0
#endif
+480
View File
@@ -0,0 +1,480 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "s3d.h"
#include "wld.h"
// #include "mob.h"
// #define FRAG_DEBUG
int WLD_GetObjectMesh(wld_object *obj, char *name, Mesh **mesh);
#define WORD_A(c) sizeof(short) * (c)
#define LONG_A(c) sizeof(long) * (c)
#define WORD_P(offset) *((short *) (buf + pos + (offset)))
#define LONG_P(offset) *((long *) (buf + pos + (offset)))
uchar encarr[] = {0x95, 0x3A, 0xC5, 0x2A, 0x95, 0x7A, 0x95, 0x6A};
void decode(uchar *str, int len) { int i; for(i = 0; i < len; ++i) str[i] ^= encarr[i % 8]; }
FRAGMENT_FUNC(Data03) {
int i, pos, nameLen,r;
WLDTexture *tex = (WLDTexture *) malloc(sizeof(WLDTexture));
tex->count = *((long *) buf) + 1;
tex->flags = (int *) malloc(sizeof(int) * tex->count);
tex->filenames = (char **) malloc(sizeof(char *) * tex->count);
*obj = (void *) tex;
#ifdef FRAG_DEBUG
printf("Data03: %p %p\n", obj, *obj);
#endif
pos = sizeof(long);
for(i = 0; i < tex->count; ++i) {
nameLen = *((short *) (buf + pos));
tex->filenames[i] = (char *) malloc(nameLen + 1);
memcpy(tex->filenames[i], (char *) (buf + pos + sizeof(short)), nameLen + 1);
decode(tex->filenames[i], nameLen);
for(r = 0; r < nameLen; r++) {
(tex->filenames[i])[r] = tolower((tex->filenames[i])[r]);
}
// Lower(tex->filenames[i]);
}
return 0;
}
FRAGMENT_FUNC(Data04) {
int flags, i, pos;
WLDTexture *tex = (WLDTexture *) malloc(sizeof(WLDTexture));
tex->count = *((long *) (buf + sizeof(long)));
tex->flags = (int *) malloc(sizeof(int) * tex->count);
tex->filenames = (char **) malloc(sizeof(char *) * tex->count);
*obj = (void *) tex;
#ifdef FRAG_DEBUG
printf("Data04: %p %p\n", obj, *obj);
#endif
flags = *((long *) buf);
pos = sizeof(long) * 2;
if(flags & (1 << 2))
pos += sizeof(long);
if(flags & (1 << 3))
pos += sizeof(long);
for(i = 0; i < 1 /* tex->count */; ++i) {
tex->flags[i] = flags;
tex->filenames[i] = ((WLDTexture *) wld->frags[*((long *) (buf + pos)) - 1]->frag)->filenames[i];
pos += sizeof(long);
}
return 0;
}
FRAGMENT_FUNC(Data05) {
*obj = wld->frags[*((long *) buf) - 1]->frag;
#ifdef FRAG_DEBUG
printf("Data05: %p %p\n", obj, *obj);
#endif
return 0;
}
FRAGMENT_FUNC(Data15) {
char *name, *temp;
WLDPlaceable *place = (WLDPlaceable *) malloc(sizeof(WLDPlaceable));
struct_Data15 *hdr = (struct_Data15 *) buf;
if(((signed long) -hdr->ref) < (signed long) 0)
return -1;
name = (char *) malloc(strlen(&wld->sHash[-hdr->ref]) - 9 + 1);
memcpy(name, &wld->sHash[-hdr->ref], strlen(&wld->sHash[-hdr->ref]) - 9);
name[strlen(&wld->sHash[-hdr->ref]) - 9] = 0;
temp = (char *) malloc(strlen(name) + 13);
sprintf(temp, "%s_DMSPRITEDEF", name);
WLD_GetObjectMesh(wld, temp, &place->mesh);
if(!place->mesh) {
printf("Object not found: %s. Original Name: %s. Cut Name: %s\n", temp, &wld->sHash[-hdr->ref], name);
return 0;
}
free(name);
place->trans[0] = hdr->trans[0];
place->trans[1] = hdr->trans[1];
place->trans[2] = hdr->trans[2];
place->rot[0] = hdr->rot[2] / 512.f * 360.f;
place->rot[1] = hdr->rot[1] / 512.f * 360.f;
place->rot[2] = hdr->rot[0] / 512.f * 360.f;
place->scale[0] = hdr->scale[2];
place->scale[1] = hdr->scale[1];
place->scale[2] = hdr->scale[0];
if(wld->placeable == null)
wld->placeable_cur = wld->placeable = (Placeable_LL *) malloc(sizeof(Placeable_LL));
else
wld->placeable_cur = wld->placeable_cur->next = (Placeable_LL *) malloc(sizeof(Placeable_LL));
wld->placeable_cur->obj = place;
wld->placeable_cur->next = null;
return 0;
}
FRAGMENT_FUNC(Data21) {
struct_Data21 *data;
long count = *((long *) buf);
long i;
BSP_Node *tree = (BSP_Node *) malloc(count * sizeof(BSP_Node));
// Build the BSP Tree
//
for(i = 0; i < count; ++i) {
tree[i].node_number=i;
data = (struct_Data21 *) (buf + (i * sizeof(struct_Data21)) + 4);
tree[i].normal[0] = data->normal[0];
tree[i].normal[1] = data->normal[1];
tree[i].normal[2] = data->normal[2];
tree[i].splitdistance = data->splitdistance;
tree[i].region = data->region;
tree[i].left = data->node[0];
tree[i].right = data->node[1];
}
*obj = (void *) tree;
return 0;
}
FRAGMENT_FUNC(Data22) {
int pos;
uchar *data6area ;
struct_Data22 *data = (struct_Data22 *) buf;
if(!wld->loadBSP)
return -1;
pos = sizeof(struct_Data22) + (12 * data->size1) + (8 * data->size2);
// Derision: We don't need any of the data from this fragment for determining the water/lava
// areas, however I left the following code here for possible future use.
// The four floats are the x,y,z of the centre of the region and the max distance of any point
// in the region from the centre.
data6area = buf + pos;
data6area = data6area + ((data->size5) * 7 * 4);
unsigned short d6size = *((unsigned short *) data6area);
data6area = data6area + 2; // Move past d6 size
data6area = data6area + d6size; // Move past RLE data ? Hopefully;
float f1, f2, f3, f4;
f1 = *((float *) data6area);
f2 = *((float *) (data6area+4));
f3 = *((float *) (data6area+8));
f4 = *((float *) (data6area+12));
//if(data->flags==0x181) printf("Frag 36 reference?: %ld\n", *((long *) (data6area+20)));
return 0;
}
FRAGMENT_FUNC(Data29) {
long a,flags, numregions, lenstr;
struct_Data29 *data29 = (struct_Data29 *) malloc(sizeof(struct_Data29));
*obj = (void *) data29;
flags = *buf;
numregions = *((long *)(buf+4));
data29->region_count = numregions ;
data29->region_array = (long *)malloc(numregions * sizeof(long));
for(a=0;a<numregions;a++) {
data29->region_array[a] = *((long *)(buf+8+(a*4)));
}
lenstr = *((long *)(buf+8+(numregions*4)));
data29->strlen=lenstr;
if(lenstr==0) {
data29->region_type = -1 ; // Flag the type as unknown. Later processing will set it to a default type.
return 0 ;
}
data29->str = (char *)malloc(lenstr);
char *encstr;
encstr = buf+8+(++a*4);
decode(encstr, lenstr);
strcpy(data29->str, encstr);
if(lenstr>=2)
if(!strncmp(encstr,"WT",2)) data29->region_type = 1; // Water
else if(!strncmp(encstr,"LA",2)) data29->region_type = 2; // Lava
else if(!strncmp(encstr,"DR",2)) data29->region_type = 3; // Zone Line ?
else data29->region_type = -2; // Flag this so that it doesn't get set to the default water or lava
// later, because it is neither.
//
return 0 ;
}
FRAGMENT_FUNC(Data30) {
WLDTexture *temp;
int params;
params = *((long *) (buf + 4));
if(!params || !*((long *) (buf + 20))) {
*obj = (void *) malloc(sizeof(WLDTexture));
temp = (WLDTexture *) *obj;
temp->count = 1;
temp->filenames = (char **) malloc(sizeof(char *));
temp->filenames[0] = "collide.dds";
temp->flags = (int *) malloc(sizeof(int));
temp->flags[0] = 0;
}
else {
if(!*((long *) buf))
*obj = wld->frags[*((long *) (buf + 28)) - 1]->frag;
else
*obj = wld->frags[*((long *) (buf + 20)) - 1]->frag;
((WLDTexture *) *obj)->params = params;
}
#ifdef FRAG_DEBUG
printf("Data30: %p %p\n", obj, *obj);
#endif
return 0;
}
FRAGMENT_FUNC(Data31) {
int i, pos;
WLDTexture *tex = (WLDTexture *) malloc(sizeof(WLDTexture));
tex->count = *((long *) (buf + sizeof(long)));
tex->flags = (int *) malloc(sizeof(int) * tex->count);
tex->filenames = (char **) malloc(sizeof(char *) * tex->count);
*obj = (void *) tex;
#ifdef FRAG_DEBUG
printf("Data31: %p %p\n", obj, *obj);
#endif
pos = sizeof(long) * 2;
for(i = 0; i < tex->count; ++i) {
tex->flags[i] = ((WLDTexture *) wld->frags[*((long *) (buf + pos)) - 1]->frag)->flags[0];
tex->filenames[i] = ((WLDTexture *) wld->frags[*((long *) (buf + pos)) - 1]->frag)->filenames[0];
tex->params = ((WLDTexture *) wld->frags[*((long *) (buf + pos)) - 1]->frag)->params;
pos += sizeof(long);
}
return 0;
}
FRAGMENT_FUNC(Data36) {
struct_Data36 *header = (struct_Data36 *) buf;
WLDVertex *verti = (WLDVertex *) malloc(header->vertexCount * sizeof(WLDVertex));
Poly *poly = (Poly *) malloc(header->polygonsCount * sizeof(Poly));
WLDPolygon *p;
TexCoordsNew *tex_new;
TexCoordsOld *tex_old;
Vert *v;
Mesh *mesh = (Mesh *) malloc(sizeof(Mesh));
int i, j, polyCount, vertCount, texIndex, skinIndex, pc, pos = sizeof(struct_Data36);
float scale = 1.0f / (float) (1 << header->scale);
mesh->name = -frag_name;
mesh->tex = ((WLDTexture *) wld->frags[header->fragment1 - 1]->frag);
mesh->polygonCount = header->polygonsCount;
mesh->vertexCount = header->vertexCount;
for(i = 0; i < header->vertexCount; ++i) {
v = (Vert *) (buf + pos);
verti[i].x = header->centerX + v->x * scale;
verti[i].y = header->centerY + v->y * scale;
verti[i].z = header->centerZ + v->z * scale;
pos += sizeof(Vert);
}
if(wld->_new) {
for(i = 0; i < header->texCoordsCount; ++i) {
tex_new = (TexCoordsNew *) (buf + pos);
verti[i].u = tex_new->tx / 256.0f;
verti[i].v = tex_new->tz / 256.0f;
pos += sizeof(TexCoordsNew);
}
}
else {
for(i = 0; i < header->texCoordsCount; ++i) {
tex_old = (TexCoordsOld *) (buf + pos);
verti[i].u = tex_old->tx / 256.0f;
verti[i].v = tex_old->tz / 256.0f;
pos += sizeof(TexCoordsOld);
}
}
pos += 3 * header->normalsCount;
pos += 4 * header->colorCount;
for(i = 0; i < header->polygonsCount; ++i) {
p = (WLDPolygon *) (buf + pos);
poly[i].flags = p->flags;
poly[i].v1 = p->v1;
poly[i].v2 = p->v2;
poly[i].v3 = p->v3;
pos += sizeof(WLDPolygon);
}
pc = 0;
for(i = 0; i < header->size6; ++i) {
vertCount = *((short *) (buf + pos));
skinIndex = *((short *) (buf + pos + 2));
for(j = 0; j < vertCount; ++j, ++pc) {
verti[pc].skin = skinIndex;
}
pos += 4;
}
pc = 0;
for(i = 0; i < header->polygonTexCount; ++i) {
polyCount = *((short *) (buf + pos));
texIndex = *((short *) (buf + pos + 2));
for(j = 0; j < polyCount; ++j, ++pc)
poly[pc].tex = texIndex;
pos += 4;
}
mesh->verti = verti;
mesh->poly = poly;
*obj = (void *) mesh;
#ifdef FRAG_DEBUG
printf("Data36: %p %p\n", obj, *obj);
#endif
return 0;
}
int WLD_Init(wld_object *obj, uchar *wld, s3d_object *s3d, char loadBSP) {
int pos, i, status;
void *frag_obj;
struct_wld_header *header;
struct_wld_basic_frag *frag;
obj->wld = wld;
obj->s3d = s3d;
header = (struct_wld_header *) wld;
pos = sizeof(struct_wld_header);
if(header->magic != 0x54503d02)
return -1;
if(header->version == 0x00015500)
obj->_new = 0;
else
obj->_new = 1;
obj->sHash = wld + pos;
decode(obj->sHash, header->stringHashSize);
obj->frags = (struct_frag **) malloc(sizeof(struct_frag *) * header->fragmentCount);
obj->fragCount = header->fragmentCount;
obj->loadBSP = loadBSP;
obj->placeable = null;
pos += header->stringHashSize;
for(i = 0; i < header->fragmentCount; ++i) {
frag = (struct_wld_basic_frag *) (wld + pos);
obj->frags[i] = (struct_frag *) malloc(sizeof(struct_frag));
switch(frag->id) {
case 0x35: status = -1; break;
case 0x03: FRAGMENT(Data03); break;
case 0x04: FRAGMENT(Data04); break;
case 0x05: FRAGMENT(Data05); break;
case 0x15: FRAGMENT(Data15); break;
case 0x21: FRAGMENT(Data21); break;
case 0x22: FRAGMENT(Data22); break;
case 0x29: FRAGMENT(Data29); break;
case 0x30: FRAGMENT(Data30); break;
case 0x31: FRAGMENT(Data31); break;
case 0x36: FRAGMENT(Data36); break;
}
#ifdef FRAG_DEBUG
if(frag->id != 0x35)
printf("Init: %i - %p\n", i, frag_obj);
#endif
obj->frags[i]->type = frag->id;
obj->frags[i]->name = frag->nameRef;
obj->frags[i]->frag = frag_obj;
pos += sizeof(struct_wld_basic_frag) + frag->size - 4;
}
return 0;
}
int WLD_GetObjectMesh(wld_object *obj, char *name, Mesh **mesh) {
int i;
for(i = 0; i < obj->objs->fragCount; ++i) {
if(obj->objs->frags[i]->type != 0x36)
continue;
if(!strcmp(&obj->objs->sHash[-obj->objs->frags[i]->name], name)) {
*mesh = (Mesh *) obj->objs->frags[i]->frag;
return 0;
}
}
return -1;
}
int WLD_GetZoneMesh(wld_object *obj, ZoneMesh *mesh) {
Mesh *temp = NULL;
int i, j;
int polygonCount = 0, vertexCount = 0;
for(i = 0; i < obj->fragCount; ++i) {
if(obj->frags[i]->type != 0x36)
continue;
temp = (Mesh *) obj->frags[i]->frag;
polygonCount += temp->polygonCount;
vertexCount += temp->vertexCount;
}
mesh->polygonCount = polygonCount;
mesh->vertexCount = vertexCount;
mesh->poly = (Poly **) malloc(sizeof(Poly *) * polygonCount);
mesh->verti = (WLDVertex **) malloc(sizeof(WLDVertex *) * vertexCount);
polygonCount = 0;
vertexCount = 0;
if(temp != NULL)
mesh->tex = temp->tex;
for(i = 0; i < obj->fragCount; ++i) {
if(obj->frags[i]->type != 0x36)
continue;
temp = (Mesh *) obj->frags[i]->frag;
for(j = 0; j < temp->polygonCount; ++j) {
mesh->poly[polygonCount + j] = &temp->poly[j];
mesh->poly[polygonCount + j]->v1 += vertexCount;
mesh->poly[polygonCount + j]->v2 += vertexCount;
mesh->poly[polygonCount + j]->v3 += vertexCount;
}
for(j = 0; j < temp->vertexCount; ++j) {
mesh->verti[vertexCount + j] = &temp->verti[j];
}
polygonCount += temp->polygonCount;
vertexCount += temp->vertexCount;
}
return 0;
}
+195
View File
@@ -0,0 +1,195 @@
#ifndef __EQCLIENT_WLD_H_
#define __EQCLIENT_WLD_H_
#include "s3d.h"
#include "types.h"
#define FRAGMENT(name) status = name(&frag_obj, obj, (wld + pos + sizeof(struct_wld_basic_frag)), frag->size, frag->nameRef)
#define FRAGMENT_FUNC(name) int name(void **obj, wld_object *wld, uchar *buf, int len, int frag_name)
typedef struct struct_wld_header {
long magic;
long version;
long fragmentCount;
long header3;
long header4;
long stringHashSize;
long header6;
} struct_wld_header;
typedef struct struct_wld_basic_frag {
long size;
long id;
long nameRef;
} struct_wld_basic_frag;
typedef struct struct_Data36 {
long flags;
long fragment1;
long fragment2;
long fragment3;
long fragment4;
float centerX;
float centerY;
float centerZ;
long params2[3]; // 48
float maxDist;
float minX;
float minY;
float minZ;
float maxX;
float maxY;
float maxZ; // 24
short int vertexCount;
short int texCoordsCount;
short int normalsCount;
short int colorCount;
short int polygonsCount;
short int size6;
short int polygonTexCount;
short int vertexTexCount;
short int size9;
short int scale; // 20
} struct_Data36;
struct Data10 {
long flags, size1, fragment;
};
typedef struct WLDVertex {
double x, y, z;
float u, v;
short skin;
} WLDVertex;
typedef struct Vert {
signed short int x, y, z;
} Vert;
typedef struct TexCoordsNew {
signed long tx, tz;
} TexCoordsNew;
typedef struct TexCoordsOld {
signed short int tx, tz;
} TexCoordsOld;
typedef struct VertexNormal {
signed char nx, ny, nz;
} VertexNormal;
typedef struct VertexColor {
char color[4];
} VertexColor;
typedef struct WLDPolygon {
short int flags, v1, v2, v3;
} WLDPolygon;
typedef struct Poly {
long int flags, v1, v2, v3, tex;
} Poly;
typedef struct WLDTexture {
int count;
int *flags;
int params;
char **filenames;
uint32 *textures;
} WLDTexture;
typedef struct Mesh {
long name;
long polygonCount;
long vertexCount;
WLDVertex *verti;
Poly *poly;
WLDTexture *tex;
} Mesh;
typedef struct ZoneMesh {
long name;
long polygonCount;
long vertexCount;
WLDVertex **verti;
Poly **poly;
WLDTexture *tex;
} ZoneMesh;
typedef struct struct_frag {
long type;
long name;
void *frag;
}struct_frag;
typedef struct struct_Data21 {
float normal[3], splitdistance;
long region, node[2];
} struct_Data21;
typedef struct struct_Data22 {
long flags, fragment1, size1, size2, params1, size3, size4, params2, size5, size6;
} struct_Data22;
typedef struct struct_Data29 {
long region_count;
long *region_array;
long strlen;
char *str;
int region_type; // We fill this in with -1 for unknown, 1 for water, 2 for lava
} struct_Data29;
/*typedef struct BSP_Region {
} BSP_Region;*/
typedef struct BSP_Node {
long node_number;
float normal[3], splitdistance;
long region;
int special;
long left, right;
} BSP_Node;
typedef struct struct_Data15 {
uint32 ref, flags, fragment1;
float trans[3], rot[3];
float scale[3];
uint32 fragment2, flags2;
} struct_Data15;
typedef struct WLDPlaceable {
float trans[3], rot[3], scale[3];
Mesh *mesh;
} WLDPlaceable;
typedef struct Placeable_LL {
WLDPlaceable *obj;
struct Placeable_LL *next;
} Placeable_LL;
typedef struct wld_object {
int fragCount;
char loadBSP;
uchar *wld;
uchar *sHash;
uint8 _new;
s3d_object *s3d;
Placeable_LL *placeable, *placeable_cur;
struct wld_object *objs;
struct_frag **frags;
} wld_object;
#ifdef __cplusplus
extern "C" {
#endif
int WLD_Init(wld_object *obj, uchar *wld, s3d_object *s3d, char loadBSP);
int WLD_GetZoneMesh(wld_object *obj, ZoneMesh *mesh);
#ifdef __cplusplus
}
#endif
#endif
+299
View File
@@ -0,0 +1,299 @@
#include <stdio.h>
#include <string.h>
#include "3d.hpp"
#include "zon.hpp"
ZonLoader::ZonLoader() {
this->buffer = NULL;
this->buf_len = -1;
this->archive = NULL;
this->status = 0;
}
ZonLoader::~ZonLoader() {
this->Close();
}
int ZonLoader::Open(char *base_path, char *zone_name, Archive *archive) {
uchar *buffer;
int buf_len;
Texture **tex;
int tex_count, tex_tmp, *tex_map;
int i, j, k, l, len;
char **model_names;
char *filename;
uchar *zon_tmp, *zon_orig;
float rot_change = 180.0f / 3.14159f;
// float rot_change = 1.0f;
float base[3];
// filename = new char[strlen(zone_name) + 5];
// sprintf(filename, "%s.zon", zone_name);
const char *fn = archive->FindExtension(".zon");
if(fn == NULL) {
printf("Unable to find a .zon file in %s\n", zone_name);
//try looking just for the .ter file...
const char *tfn = archive->FindExtension(".ter");
if(tfn == NULL)
return(0);
if(this->terloader.Open(NULL, (char *) tfn, archive) == 0) {
printf("failed to direct load TER file in %s\n", zone_name);
return(0);
}
printf("Got direct TER, it is %p\n", terloader.model_data.zone_model);
this->model_data.zone_model = terloader.model_data.zone_model;
return 1;
}
filename = new char[strlen(fn)+1];
strcpy(filename, fn);
if(!archive->GetFile(filename, &buffer, &buf_len)) {
printf("Unable to load '%s' from '%s'\n", filename, zone_name);
delete[] filename;
return 0;
}
printf("Writting ZON to '%s'\n", filename);
FILE *ttt = fopen(filename, "wb");
fwrite(buffer, 1, buf_len, ttt);
fclose(ttt);
delete[] filename;
zon_header *hdr = (zon_header *) buffer;
zon_placeable *plac;
if(hdr->magic[0] != 'E' || hdr->magic[1] != 'Q' || hdr->magic[2] != 'G' || hdr->magic[3] != 'Z') {
printf("Bad file header in ZON %s\n", zone_name);
return 0;
}
buffer += sizeof(zon_header);
//search for a nice TER file...
uchar *buf_end = buffer + buf_len;
while(buffer < buf_end) {
if(strstr((const char *) buffer, ".ter") != NULL || strstr((const char *) buffer, ".TER") != NULL) {
if(this->terloader.Open(NULL, (char *) buffer, archive) == 0) {
printf("failed to load TER file in %s\n", zone_name);
return(0);
}
printf("Got TER, it is %p\n", terloader.model_data.zone_model);
this->model_data.zone_model = terloader.model_data.zone_model;
break;
}
buffer += strlen((const char *) buffer)+1;
}
return 1;
/*******************************************/
zon_orig = buffer;
zon_tmp = buffer + hdr->list_len;
buffer += strlen((char *) buffer) + 1;
i = 0;
while(buffer < zon_tmp) {
len = strlen((char *) buffer);
if(buffer[len - 4] == '.')
++i;
buffer += len + 1;
}
this->model_data.model_count = i;
model_names = new char *[this->model_data.model_count];
this->model_data.models = new Model *[this->model_data.model_count];
buffer = zon_orig;
buffer += strlen((char *) buffer) + 1;
i = 0;
while(buffer < zon_tmp) {
len = strlen((char *) buffer);
if(buffer[len - 4] == '.') {
model_names[i] = (char *) buffer;
++i;
}
buffer += len + 1;
}
buffer = zon_orig + hdr->list_len + hdr->unid * 4;
this->model_data.plac_count = hdr->obj_count - 1;
this->model_data.plac_count = 0;
// this->model_data.placeable = new Placeable *[this->model_data.plac_count];
this->model_data.placeable = 0;
plac = (zon_placeable *) buffer;
base[0] = plac->x;
base[1] = plac->y;
base[2] = plac->z;
printf("(%f %f %f) (%f %f %f)\n", plac->x, plac->y, plac->z, plac->rz, plac->ry, plac->rx);
buffer += sizeof(zon_placeable);
for(i = 0; i < this->model_data.plac_count; ++i) {
plac = (zon_placeable *) buffer;
zon_tmp = zon_orig + plac->loc;
this->model_data.placeable[i] = new Placeable;
this->model_data.placeable[i]->x = plac->x;
this->model_data.placeable[i]->y = plac->y;
this->model_data.placeable[i]->z = plac->z;
this->model_data.placeable[i]->rx = plac->rz * rot_change;
this->model_data.placeable[i]->ry = plac->ry * rot_change;
this->model_data.placeable[i]->rz = plac->rx * rot_change;
this->model_data.placeable[i]->scale[0] = plac->scale;
this->model_data.placeable[i]->scale[1] = plac->scale;
this->model_data.placeable[i]->scale[2] = plac->scale;
this->model_data.placeable[i]->model = -1;
#ifdef DEBUG_MODE
printf("%s (%f %f %f) (%f %f %f) %f\n",
zon_tmp,
this->model_data.placeable[i]->x,
this->model_data.placeable[i]->y,
this->model_data.placeable[i]->z,
this->model_data.placeable[i]->rx,
this->model_data.placeable[i]->ry,
this->model_data.placeable[i]->rz,
this->model_data.placeable[i]->scale);
#endif
while(zon_tmp[strlen((char *) zon_tmp) - 4] != '.')
zon_tmp += strlen((char *) zon_tmp) + 1;
for(j = 0; j < this->model_data.model_count; ++j) {
if(!strcmp(model_names[j], (char *) zon_tmp)) {
this->model_data.placeable[i]->model = j;
break;
}
}
buffer += sizeof(zon_placeable);
}
// model_loaders = new TERLoader[this->model_data.model_count];
model_loaders = 0;
tex_count = this->model_data.zone_model->tex_count;
for(j = 0; j < this->model_data.model_count; ++j) {
model_loaders[j].Open(NULL, model_names[j], archive);
this->model_data.models[j] = new Model;
this->model_data.models[j]->vert_count = model_loaders[j].model_data.zone_model->vert_count;
this->model_data.models[j]->poly_count = model_loaders[j].model_data.zone_model->poly_count;
this->model_data.models[j]->tex_count = model_loaders[j].model_data.zone_model->tex_count;
this->model_data.models[j]->verts = model_loaders[j].model_data.zone_model->verts;
this->model_data.models[j]->polys = model_loaders[j].model_data.zone_model->polys;
this->model_data.models[j]->tex = model_loaders[j].model_data.zone_model->tex;
tex_tmp = 1;
for(i = 0; i < this->model_data.models[j]->tex_count; ++i) {
for(k = 0; k < this->model_data.zone_model->tex_count; ++k) {
if((!this->model_data.zone_model->tex[k]->filenames[0] && !this->model_data.models[j]->tex[i]->filenames[0]) ||
(this->model_data.zone_model->tex[k]->filenames[0] &&
this->model_data.models[j]->tex[i]->filenames[0] &&
!strcmp(this->model_data.zone_model->tex[k]->filenames[0], this->model_data.models[j]->tex[i]->filenames[0]))) {
tex_tmp = 0;
break;
}
}
if(tex_tmp)
++tex_count;
else {
for(k = 0; k < j; ++k) {
for(l = 0; l < this->model_data.models[k]->tex_count; ++l) {
if(this->model_data.models[k]->tex[l]->filenames[0] == this->model_data.models[j]->tex[i]->filenames[0] ||
(this->model_data.models[k]->tex[l]->filenames[0] &&
this->model_data.models[j]->tex[i]->filenames[0] &&
!strcmp(this->model_data.models[k]->tex[l]->filenames[0], this->model_data.models[j]->tex[i]->filenames[0]))) {
tex_tmp = 0;
break;
}
}
}
if(tex_tmp)
++tex_count;
}
}
}
printf("%i\n", tex_count);
tex = new Texture *[tex_count];
tex_count = this->model_data.zone_model->tex_count;
tex_tmp = 1;
for(i = 0; i < tex_count; ++i)
tex[i] = this->model_data.zone_model->tex[i];
for(i = 0; i < this->model_data.model_count; ++i) {
for(j = 0; j < this->model_data.models[i]->tex_count; ++j) {
for(k = 0; k < tex_count; ++k) {
if(tex[k]->filenames[0] == this->model_data.models[i]->tex[j]->filenames[0] ||
(tex[k]->filenames[0] &&
this->model_data.models[i]->tex[j]->filenames[0] &&
!strcmp(tex[k]->filenames[0], this->model_data.models[i]->tex[j]->filenames[0]))) {
tex_tmp = 0;
break;
}
}
if(tex_tmp) {
tex[tex_count] = this->model_data.models[i]->tex[j];
++tex_count;
}
}
}
for(i = 0; i < this->model_data.model_count; ++i) {
tex_map = new int[this->model_data.models[i]->tex_count];
for(j = 0; j < this->model_data.models[i]->tex_count; ++j) {
tex_map[j] = 0;
for(k = 0; k < tex_count; ++k) {
if(tex[k]->filenames[0] == this->model_data.models[i]->tex[j]->filenames[0] ||
(tex[k]->filenames[0] &&
this->model_data.models[i]->tex[j]->filenames[0] &&
!strcmp(tex[k]->filenames[0], this->model_data.models[i]->tex[j]->filenames[0]))) {
tex_map[j] = k;
break;
}
}
}
for(j = 0; j < this->model_data.models[i]->poly_count; ++j)
this->model_data.models[i]->polys[j]->tex = tex_map[this->model_data.models[i]->polys[j]->tex];
delete[] tex_map;
}
delete[] this->model_data.zone_model->tex;
this->model_data.zone_model->tex = tex;
this->model_data.zone_model->tex_count = tex_count;
this->status = 1;
return 1;
}
// ... in my pants.
int ZonLoader::Close() {
int i;
if(!this->status)
return 1;
this->terloader.Close();
for(i = 0; i < this->model_data.model_count; ++i)
this->model_loaders[i].Close();
delete[] this->model_loaders;
return 1;
}
+42
View File
@@ -0,0 +1,42 @@
#ifndef __OPENEQ_ZON__
#define __OPENEQ_ZON__
#include "ter.hpp"
/* Big thanks to jbb on the ZON stuff! */
#pragma pack(1)
struct zon_header {
char magic[4]; // Constant at EQGZ
long version; // Constant at 2
long list_len; // Length of the list to follow.
long unid; // Number of 4 byte entries in an unidentified table.
long obj_count; // Placeable object count.
long unk[2]; // Unknown.
} typedef zon_header;
struct zon_placeable {
long id;
long loc;
float x, y, z;
float rx, ry, rz;
float scale;
} typedef zon_placeable;
#pragma pack()
class ZonLoader : public FileLoader {
public:
ZonLoader();
~ZonLoader();
virtual int Open(char *base_path, char *zone_name, Archive *archive);
virtual int Close();
private:
TERLoader terloader;
TERLoader *model_loaders;
};
#endif