EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Archive::Tools (https://www.eqemulator.org/forums/forumdisplay.php?f=623)
-   -   Omens Of War .TER File Format (https://www.eqemulator.org/forums/showthread.php?t=15876)

daeken_bb 09-15-2004 03:47 AM

Omens Of War .TER File Format
 
I've started reverse-engineering the .TER file format that's used in OoW zones and what follows is my progress thus far.

The header is as follows:

Code:

struct Header {
  char magic[4]; // Constant at EQGT
  uint32 unk1; // Seems constant at 2... version?
  uint32 list_length; // This is the size of the object/property list that follows
  uint32 object_count; // This is the number of objects in the list (NOT the number of elements total)
  uint32 vertex_count; // This seems to be the count of vertices in the mesh.
  uint32 poly_count; // Seems to be the count of polygons in the mesh.
};

After the header comes a list of objects and their properties.
Each element is a null-terminated name followed by a null-terminated value.
If the name starts with 'e_' it is a property of the previous object named, otherwise it's naming a new object and its associated base texture.

For example, the list for wall of slaughter is:

colmap01 colmap01.dds
e_TextureDiffuse0 palmap01a.bmp
e_TexturePalette0 HW_rd01_c.dds
e_TextureDetail0 e_fScale0
e_fGrassDensity0 FT_RD2_c.dds
e_TextureDetail1 e_fScale1
e_fGrassDensity1 FT_path01.dds
e_TextureDetail2 e_fScale2
e_fGrassDensity2 FT_plateau01.dds
e_TextureDetail3 e_fScale3
e_fGrassDensity3 FT_grass01.dds
e_TextureDetail4 e_fScale4
e_fGrassDensity4 FT_plateau02.dds
e_TextureDetail5 e_fScale5
e_fGrassDensity5 None
e_TextureDetail6 e_fScale6
e_fGrassDensity6 None
e_TextureDetail7 e_fScale7
e_fGrassDensity7 None
e_TextureDetail8 e_fScale8
e_fGrassDensity8 None
e_TextureDetail9 e_fScale9
e_fGrassDensity9 Opaque_MaxC1DTP.fx
colmap02 colmap02.dds
e_TextureDiffuse0 palmap02a.bmp
e_TexturePalette0 HW_rd01_c.dds
e_TextureDetail0 e_fScale0
e_fGrassDensity0 FT_RD2_c.dds
e_TextureDetail1 e_fScale1
e_fGrassDensity1 FT_path01.dds
e_TextureDetail2 e_fScale2
e_fGrassDensity2 FT_plateau01.dds
e_TextureDetail3 e_fScale3
e_fGrassDensity3 FT_grass01.dds
e_TextureDetail4 e_fScale4
e_fGrassDensity4 FT_plateau02.dds
e_TextureDetail5 e_fScale5
e_fGrassDensity5 None
e_TextureDetail6 e_fScale6
e_fGrassDensity6 None
e_TextureDetail7 e_fScale7
e_fGrassDensity7 None
e_TextureDetail8 e_fScale8
e_fGrassDensity8 None
e_TextureDetail9 e_fScale9
e_fGrassDensity9 Opaque_MaxC1DTP.fx
colmap03 colmap03.dds
e_TextureDiffuse0 palmap03a.bmp
e_TexturePalette0 HW_rd01_c.dds
e_TextureDetail0 e_fScale0
e_fGrassDensity0 FT_RD2_c.dds
e_TextureDetail1 e_fScale1
e_fGrassDensity1 FT_path01.dds
e_TextureDetail2 e_fScale2
e_fGrassDensity2 FT_plateau01.dds
e_TextureDetail3 e_fScale3
e_fGrassDensity3 FT_DRD2_c.dds
e_TextureDetail4 e_fScale4
e_fGrassDensity4 FT_plateau02.dds
e_TextureDetail5 e_fScale5
e_fGrassDensity5 None
e_TextureDetail6 e_fScale6
e_fGrassDensity6 None
e_TextureDetail7 e_fScale7
e_fGrassDensity7 None
e_TextureDetail8 e_fScale8
e_fGrassDensity8 None
e_TextureDetail9 e_fScale9
e_fGrassDensity9 Opaque_MaxC1DTP.fx
colmap04 colmap04.dds
e_TextureDiffuse0 palmap04a.bmp
e_TexturePalette0 HW_rd01_c.dds
e_TextureDetail0 e_fScale0
e_fGrassDensity0 FT_RD2_c.dds
e_TextureDetail1 e_fScale1
e_fGrassDensity1 FT_path01.dds
e_TextureDetail2 e_fScale2
e_fGrassDensity2 FT_plateau01.dds
e_TextureDetail3 e_fScale3
e_fGrassDensity3 FT_DRD2_c.dds
e_TextureDetail4 e_fScale4
e_fGrassDensity4 FT_plateau02.dds
e_TextureDetail5 e_fScale5
e_fGrassDensity5 None
e_TextureDetail6 e_fScale6
e_fGrassDensity6 None
e_TextureDetail7 e_fScale7
e_fGrassDensity7 None
e_TextureDetail8 e_fScale8
e_fGrassDensity8 None
e_TextureDetail9 e_fScale9
e_fGrassDensity9 Opaque_MaxC1DTP.fx
tunn04 sp_tunn04.dds
e_TextureDiffuse0 sp_tunn04_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
tunn05 sp_tunn05.dds
e_TextureDiffuse0 sp_tunn05_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
tunn06 sp_tunn06.dds
e_TextureDiffuse0 sp_tunn06_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
tunn07 tunn07.dds
e_TextureDiffuse0 tunn07_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ab_wall_T01 sp_ft_wall_high.dds
e_TextureDiffuse0 Di_ent_cinderblock01_mid_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ab_wall_M01 sp_ft_wall_mid.dds
e_TextureDiffuse0 Di_ent_cinderblock01_mid_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ab_wall_B01 sp_ft_wall_low.dds
e_TextureDiffuse0 Di_ent_cinderblock01_low_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ab_arch_T01 ab_arch_T01.dds
e_TextureDiffuse0 Di_ent_metal02_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ab_arch_M01 ab_arch_M01.dds
e_TextureDiffuse0 Di_ent_metal02_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ab_arch_B01 ab_arch_B01.dds
e_TextureDiffuse0 Di_ent_metal02_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ab_floor_01 ab_floor_01.dds
e_TextureDiffuse0 sp_ft_floor_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
rock18 av_rock18_c.dds
e_TextureDiffuse0 av_rock18_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
rock10 av_rock10_c.dds
e_TextureDiffuse0 av_rock10_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
rock16 av_rock16_c.dds
e_TextureDiffuse0 Di_ent_wall_crumble01_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
maze01 av_rock12_c.dds
e_TextureDiffuse0 av_rock12_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
maze02 Di_rune_plain_bkg_c.dds
e_TextureDiffuse0 Di_rune_plain_bkg_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
maze03 ab_maze01_c.dds
e_TextureDiffuse0 ab_maze01_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
maze04 Di_floor01_c.dds
e_TextureDiffuse0 Di_floor01_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
maze05 Di_Maze01_Power_c.dds
e_TextureDiffuse0 Di_Maze01_Main_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
ra_pris19 ra_prison19_c.dds
e_TextureDiffuse0 ra_prison19_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
av_pris14high av_prison14_c.dds
e_TextureDiffuse0 av_prison13a_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
av_pris22mid av_prison22_c.dds
e_TextureDiffuse0 av_prison22_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
av_pris15low av_prison15_c.dds
e_TextureDiffuse0 av_prison15_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
av_pris18flr av_prison18_c.dds
e_TextureDiffuse0 av_prison18a_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx
dn_path HW_rd01_c.dds
e_TextureDiffuse0 HW_rd01_n.dds
e_TextureNormal0 Opaque_MaxCB1.fx



I'll post more as I figure it out.

Happy Hacking,
Lord Daeken M. BlackBlade
(Cody Brocious)


Edit #1: Added the object_count element to the struct.
Edit #2: Replaced uint32 unk[2]; with the vertex_count and poly_count fields. Put the struct in code brackets.

daeken_bb 09-15-2004 04:02 AM

You can also get a proper view of it at http://home.archshadow.com/~daeken/t...tress_objs.txt

This is the debug output of my python script for decoding these files, so it's a bit messy still hehe.

daeken_bb 09-15-2004 06:53 AM

Ok... figured out more.

After the list comes the vertices.

The struct for each vertex is as follows:

Code:

struct Vertex {
  float unk1, unk2;
  float x;
  float unk3;
  float y;
  float unk4;
  float z;
  float unk5;
};

I'm working on figuring out triangles now, and then I'll work on figuring out the unknown values. My guess is that 3 of them are normals, 2 are tex coords.

daeken_bb 09-15-2004 03:28 PM

Well, I just got zone geometry rendering perfectly, albiet without textures (it's figured out, just not coded as of yet) :D

It was very, very simple.

Code:

struct Header {
  char magic[4]; // Constant at EQGT
  uint32 version; // Constant at 2.
  uint32 list_length; // This is the total length of the material list that follows
  uint32 object_count; // This is the number of materials in the list (NOT the number of elements)
  uint32 vertex_count; // Number of vertices
  uint32 poly_count; // Polygon count
};

After the header comes a list of materials and their properties.
Each element is a null-terminated name followed by a null-terminated value.
If the name starts with 'e_' it is a property of the previous material named, otherwise it's naming a new material and its associated base texture. If the base texture named starts with e_, leave the base texture empty and treat this name as its own variable. In the case of having no base texture, simply use the first e_ entry value as the texture, but make sure you also set the e_ entry in your material data.

Now comes the one portion of the file that I have yet to figure out. My theory is that it is a BSP or octree, but I have yet to test it. To skip it, seek to 3 + (vertex_count * 32) + (poly_count * 20) bytes before the end of the file. I'll work on figuring this out when I get a chance, but my knowledge of BSPs and octrees is so limited its not even funny.

Next comes the vertices. You should decode these and store them in a zero-indexed array.

Code:

struct Vertex {
  float x, y, z; // Vertex location
  float i, j, k; // Normals?
  float u, v; // Tex coords, clamped to [0,1]
};

After that comes the triangles. The v0, v1, and v2 fields index the vertex array. The group field indexes the object type list if greater than or equal to zero, else it means the object is invisible I _think_.

Code:

struct Triangle {
  unsigned long v0, v1, v2; // These are vertex indices
  signed long group; // Texture/material group id.
  unsigned long flags; // This seems to flag if you can walk through the polygon or not.
};

Then after that is simply 3 null bytes, then the end of the file.


Enjoy :D

daeken_bb 09-15-2004 04:03 PM

God anguish looks beautiful running in the python version of my ter decoder with full textures ;)

I got it working in about 10 minutes without having to change the file loader... everything was right on the first try :D

I would take screenshots, but unfortunately GLUT doesn't want to let me go windowed... Whatever. I'll have the C version rendering .ter soon anyhow :D

I will post screenshots ASAP.

jbb 09-21-2004 10:18 AM

Anguish works great in my renderer but I can't display "riftseekers" at all. I have a problem loading the texture names from the strings at the start. The names seem to get out of step. Does it work for you?

And if so could you try to explain how to get the names decoded properly if you have the time :)

Thanks

daeken_bb 09-21-2004 12:16 PM

I updated the guide (not the parent post, but one of the comments) to fix the material loading... basically, all you have to do is make sure that the base texture given isn't an e_ entry :)

jbb 09-21-2004 07:15 PM

Thanks - I'm still having trouble with this though. I think I'll do what you appeared to have done based on your post and write a decoder in python as it's so much easier to prototype stuff and then when it works recode it in c++.

jbb 09-21-2004 11:22 PM

I've had a closer look at the materials information and believe it should be formatted like this (just an extract from the riftseekers zone)

Code:

cieling
        e_fShininess0               
        Di_ct_pyrilen_ceiling_c.dds        e_TextureDiffuse0
        Di_ct_pyrilen_ceiling_8_n.dds        e_TextureNormal0
        Opaque_MaxCBSG1.fx

wall high
        e_fShininess0
        Di_ct_pyrilen_wall_high_c.dds        e_TextureDiffuse0
        Di_ct_pyrilen_wall_8_n.dds        e_TextureNormal0
        Opaque_MaxCBSG1.fx


red potion
        ra_crystowlava01_e.dds                e_TextureDiffuse0
        ra_crystow_water_n.dds                e_TextureNormal0
        ra_crystow_water_e.dds                e_TextureEnvironment0
        e_fFresnelBias
        e_fFresnelPower
        e_fWaterColor1
        e_fWaterColor2
        e_fReflectionAmount
        e_fReflectionColor
        Opaque_MaxWater.fx

silver
        e_fShininess0
        Di_ct_gelidran_silvermetal.dds                e_TextureDiffuse0
        Di_ct_gelidran_silvermetal_spec_8_n.dds        e_TextureNormal0
        Opaque_MaxCBS1.fx

It seems to start with a name and end with an effect and contain a number of effect parameters start with e_ which may or may not have a parameter before them in the file. Pretty much what you had except that there seems to be an e_TextureDiffuse0 texture for all of them which I guess will do as a base texture for the material for simple rendereing.

The effects exist as files in the RenderEffects directory on disk. I would guess that they might be encoded directx effects files and the material information in the TER file describes the parameters to them.

daeken_bb 09-21-2004 11:28 PM

Quote:

Originally Posted by jbb
I've had a closer look at the materials information and believe it should be formatted like this (just an extract from the riftseekers zone)

Code:

cieling
        e_fShininess0               
        Di_ct_pyrilen_ceiling_c.dds        e_TextureDiffuse0
        Di_ct_pyrilen_ceiling_8_n.dds        e_TextureNormal0
        Opaque_MaxCBSG1.fx

wall high
        e_fShininess0
        Di_ct_pyrilen_wall_high_c.dds        e_TextureDiffuse0
        Di_ct_pyrilen_wall_8_n.dds        e_TextureNormal0
        Opaque_MaxCBSG1.fx


red potion
        ra_crystowlava01_e.dds                e_TextureDiffuse0
        ra_crystow_water_n.dds                e_TextureNormal0
        ra_crystow_water_e.dds                e_TextureEnvironment0
        e_fFresnelBias
        e_fFresnelPower
        e_fWaterColor1
        e_fWaterColor2
        e_fReflectionAmount
        e_fReflectionColor
        Opaque_MaxWater.fx

silver
        e_fShininess0
        Di_ct_gelidran_silvermetal.dds                e_TextureDiffuse0
        Di_ct_gelidran_silvermetal_spec_8_n.dds        e_TextureNormal0
        Opaque_MaxCBS1.fx

It seems to start with a name and end with an effect and contain a number of effect parameters start with e_ which may or may not have a parameter before them in the file. Pretty much what you had except that there seems to be an e_TextureDiffuse0 texture for all of them which I guess will do as a base texture for the material for simple rendereing.

The effects exist as files in the RenderEffects directory on disk. I would guess that they might be encoded directx effects files and the material information in the TER file describes the parameters to them.

*blinks* Um... you're right... congrats... lol

Damn man... I can't believe I didn't see that before. Nice work :D

jbb 09-21-2004 11:39 PM

Now I can get riftseekers to load properly.

Just using the diffuse textures it comes out all blue and orange. I wonder if it really looks like that.

jbb 09-21-2004 11:46 PM

Dranik zone looks like this with my renderer
http://img57.exs.cx/img57/2686/render06.th.jpg

Still some work to go on the textures I think. They almost look scaled wrong although it could just be that simply rendering the diffuse texture isn't enough to get a reasonable output.

daeken_bb 09-22-2004 08:54 AM

Looks like you may be using the wrong mipmapping level perhaps? I dunno... m'be the bump mapping is neccesary to make it look good...

jbb 09-22-2004 09:12 AM

Ah, good guess :)
Setting anisotropic mipmapping mode made it look far better :)


All times are GMT -4. The time now is 12:13 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.