mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-05 03:06:38 +00:00
svn -> git Migration
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user