Gamestudio Links
Zorro Links
Newest Posts
Blobsculptor tools and objects download here
by NeoDumont. 03/28/24 03:01
Issue with Multi-Core WFO Training
by aliswee. 03/24/24 20:20
Why Zorro supports up to 72 cores?
by Edgar_Herrera. 03/23/24 21:41
Zorro Trader GPT
by TipmyPip. 03/06/24 09:27
VSCode instead of SED
by 3run. 03/01/24 19:06
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
2 registered members (Quad, aliswee), 835 guests, and 5 spiders.
Key: Admin, Global Mod, Mod
Newest Members
sakolin, rajesh7827, juergen_wue, NITRO_FOREVER, jack0roses
19043 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Open/Extract Model and Textures from WMB #482129
12/29/20 20:16
12/29/20 20:16
Joined: Dec 2020
Posts: 3
M
MooseMannequin Offline OP
Guest
MooseMannequin  Offline OP
Guest
M

Joined: Dec 2020
Posts: 3
Hello everyone, sorry if this is not the right thread, but I didn't found the right one, so
I'm not familiar with 3GS at all, and need your help.
I have the WMB files from the game and I figured out, it carry model and texture files inside. I need to extract them somehow to edit in the zbrush/maya then, but I don't know how.
I installed Gamestudio A8, but it can't open these files in any of editors. And I found out, one guy did it with Unity and some script, but it's just another one universe for me as well. I can send you the link, if you interested.
I am doing it just for fun and out of curiosity, and need your help so much, thank you gamers.
p.s. Sry if there is mistakes, am not english at all.

Re: Open/Extract Model and Textures from WMB [Re: MooseMannequin] #482130
12/29/20 20:49
12/29/20 20:49
Joined: May 2005
Posts: 868
Chicago, IL
Dooley Offline
User
Dooley  Offline
User

Joined: May 2005
Posts: 868
Chicago, IL
In the WED program, which unfortunately does not come with the free version of 3DGS, you can extract textures from a .wad file.

Re: Open/Extract Model and Textures from WMB [Re: MooseMannequin] #482131
12/30/20 09:23
12/30/20 09:23
Joined: May 2009
Posts: 5,370
Caucasus
3run Offline
Senior Expert
3run  Offline
Senior Expert

Joined: May 2009
Posts: 5,370
Caucasus
@Dooley as far as I remember, all game studio editors are working in free version (WED, MED, SED, but not sure about the GED). I remember there was a Lite-C version back in A7 times and it didn't have WED support, but it's not available anymore. Aside from that version differences are more about scene management, shader support, etc. Also it seems that the thread creator doesn't want to extract WAD files, but want to somehow extract textures/models from already compiled .WMB file. Sadly, I don't know how to do that.


Looking for free stuff?? Take a look here: http://badcom.at.ua
Support me on: https://boosty.to/3rung
Re: Open/Extract Model and Textures from WMB [Re: MooseMannequin] #482132
12/30/20 13:07
12/30/20 13:07
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
txesmi Offline
Serious User
txesmi  Offline
Serious User

Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
There is some information into http://www.conitec.net/beta/prog_mdlhmp.htm

I did some tests some time ago. It is not really hard.

Code
#include <acknex.h>

#define PRAGMA_PATH "models"

// ------------------------------------------------------------

STRING *strT = "";

TEXT *txtGlobal = {
	pos_x = 10;
	pos_y = 10;
	string = ("GLOBAL", "--------------------");
	flags = SHOW;
}

TEXT *txtObjects = {
	pos_x = 200;
	pos_y = 10;
	string = ("OBJECTS", "--------------------");
	flags = SHOW;
}

TEXT *txtMaterials = {
	pos_x = 400;
	pos_y = 10;
	string = ("MATERIALS", "--------------------");
	flags = SHOW;
}

TEXT *txtTextures = {
	pos_x = 600;
	pos_y = 10;
	string = ("TEXTURES", "--------------------");
	flags = SHOW;
}

TEXT *txtLightmaps = {
	pos_x = 800;
	pos_y = 10;
	string = ("LIGHTMAPS", "--------------------");
	flags = SHOW;
}

TEXT *txtBlocks = {
	pos_x = 1000;
	pos_y = 10;
	string = ("BLOCKS", "--------------------");
	flags = SHOW;
}

TEXT *txtPaths = {
	pos_x = 1200;
	pos_y = 10;
	string = ("PATHS", "--------------------");
//	flags = SHOW;
}

// ------------------------------------------------------------

typedef struct LIST {
	long offset; // offset of the list from the start of the WMB file, in bytes
	long length; // length of the list, in bytes
} LIST;

typedef struct WMB_HEADER {  
	char version[4];        // "WMB7"  
	LIST palettes;          // WMB1..6 only
	LIST legacy1;           // WMB1..6 only
	LIST textures;          // textures list  
	LIST legacy2;           // WMB1..6 only
	LIST pvs;               // BSP only 
	LIST bsp_nodes;         // BSP only 
	LIST materials;         // material names
	LIST legacy3;           // WMB1..6 only
	LIST legacy4;           // WMB1..6 only
	LIST aabb_hulls;        // WMB1..6 only
	LIST bsp_leafs;         // BSP only 
	LIST bsp_blocks;        // BSP only 
	LIST legacy5;           // WMB1..6 only
	LIST legacy6;           // WMB1..6 only
	LIST legacy7;           // WMB1..6 only
	LIST objects;           // entities, paths, sounds, etc.
	LIST lightmaps;         // lightmaps for blocks
	LIST blocks;            // block meshes
	LIST legacy8;           // WMB1..6 only
	LIST lightmaps_terrain; // lightmaps for terrains
} WMB_HEADER;

typedef struct TEXTURE {  
	char name[16];          // texture name, max. 16 characters  
	long width,height;      // texture size  
	long type;	            // texture type: 5 = 8888 RGBA; 4 = 888 RGB; 2 = 565 RGB; 6 = DDS; +8 = mipmaps
	long legacy[3];         // always 0
} TEXTURE;

typedef struct MATERIAL_INFO {  
	char legacy[44];        // always 0 
	char material[20];      // material name from the script, max. 20 characters
} MATERIAL_INFO;

typedef struct LIGHTMAP_TERRAIN {
	long object;            // terrain entity index into the objects list
	long width,height;      // lightmap size
} LIGHTMAP_TERRAIN;

typedef struct BLOCK {  
	float fMins[3];         // bounding box  
	float fMaxs[3];         // bounding box  
	long  lContent;         // always 0  
	long  lNumVerts;        // number of VERTEX structs that follow  
	long  lNumTris;         // number of TRIANGLE structs that follow	
	long  lNumSkins;        // number of SKIN structs that follow
} BLOCK;

typedef struct VERTEX {  
	float x,y,z;            // position  
	float tu,tv;            // texture coordinates  
	float su,sv;            // lightmap coordinates
} VERTEX;

typedef struct TRIANGLE {   
	short v1,v2,v3;         // indices into the VERTEX array  
	short skin;             // index into the SKIN array  
	long  unused;           // always 0 
} TRIANGLE;

typedef struct SKIN {  
	short texture;          // index into the textures list  
	short lightmap;         // index into the lightmaps list  
	long  material;         // index into the MATERIAL_INFO array  
	float ambient,albedo;  
	long  flags;            // bit 1 = flat (no lightmap), bit 2 = sky, bit 14 = smooth  
} SKIN;

typedef struct WMB_INFO {  
	long  type;             // 5 = INFO  
	float origin[3];        // not used  
	float azimuth;          // sun azimuth  
	float elevation;        // sun elevation  
	long  flags;            // always 127 (0x7F)  
	float version;	         // compiler version  
	byte  gamma;            // light level at black  
	byte  LMapSize;         // 0,1,2 for lightmap sizes 256x256, 512x512, or 1024x1024  
	byte  unused[2];  
	DWORD dwSunColor,dwAmbientColor; // color double word, ARGB   
	DWORD dwFogColor[4];
} WMB_INFO;

typedef struct WMB_POSITION {  
	long  type;             // 1 = POSITION  
	float origin[3];   
	float angle[3];   
	long  unused[2];  
	char  name[20];
} WMB_POSITION;

typedef struct WMB_LIGHT {  
	long  type;             // 2 = LIGHT  
	float origin[3];   
	float red,green,blue;   // color in percent, 0..100  
	float range;  
	long  flags;            // 0 = static, 2 = dynamic
} WMB_LIGHT;

typedef struct WMB_SOUND {  
	long  type;             // 4 = Sound  
	float origin[3];   
	float volume;
	float unused[2];  
	long  range;  
	long  flags;            // always 0  
	char  filename[33];
} WMB_SOUND;

typedef struct WMB_PATH {  
	long  type;	            // 6 = PATH  
	char  name[20];         // Path name  
	float fNumPoints;       // number of nodes  
	long  unused[3];        // always 0  
	long  num_edges;
} WMB_PATH;

typedef struct WMB_ENTITY {  
	long  type;             // 7 = ENTITY  
	float origin[3];  
	float angle[3];  
	float scale[3];  
	char  name[33];  
	char  filename[33];  
	char  behavior[33];  
	float skill[20];  
	long  flags;  
	float ambient;  
	float albedo;  
	long  path;             // attached path index, starting with 1, or 0 for no path
	long  entity2;          // attached entity index, starting with 1, or 0 for no attached entity  
	char  material[33];	  
	char  string1[33];  
	char  string2[33];  
	char  unused[33];
} WMB_ENTITY;

typedef struct WMB_OLD_ENTITY {  
	long  type;             // 3 = OLD ENTITY  
	float origin[3];  
	float angle[3];  
	float scale[3];  
	char  name[20];  
	char  filename[13];  
	char  behavior[20];  
	float skill[8];  
	long  flags;  
	float ambient;
} WMB_OLD_ENTITY;

typedef struct PATH_EDGE {  
	float fNode1,fNode2;    // node numbers of the edge, starting with 1
	float fLength;  
	float fBezier;  
	float fWeight;  
	float fSkill;
} PATH_EDGE;

typedef struct BSP_NODE {  
	long   legacy1[2];      // WMB1..6 only  
	short  mins[3];         // bounding box, packed shorts  
	short  maxs[3];  
	long   legacy2;         // WMB1..6 only  
	long   children[2];     // node index when >= 0, -(leaf index + 1) when < 0  
	long   legacy3[2];      // WMB1..6 only
} BSP_NODE;

typedef struct BSP_LEAF {  
	long   flags;           // content flags  
	long   pvs;             // PVS offset or -1  
	short  mins[3];         // bounding box, packed shorts  
	short  maxs[3];  
	long   legacy1[2];      // WMB1..6 only  
	long   nbspblock;       // offset into the bsp_blocks list  
	long   numblocks;       // number of bsp_blocks for this leaf
} BSP_LEAF;

typedef struct BSP_BLOCK {
  long   nblock;           // index of block in the blocks list
} BSP_BLOCK;

// ------------------------------------------------------------

var texFormats[8] = {0, 0, 565, 0, 888, 8888, 0, 0};

typedef struct TX_TEXTURE {
	TEXTURE *texture;
	char name[16];
	BYTE *buffer;
	long bufSize;
	BMAP *bmap;
	long format;
	long mipmaps;
	long width;
	long height;
	
	PANEL *panel;
} TX_TEXTURE;

typedef struct TX_LIGHTMAP {
 	BYTE *buffer;
 	BMAP *bmap;
	
	PANEL *panel;
} TX_LIGHTMAP;

typedef struct TX_TERRAIN_LIGHTMAP {
 	LIGHTMAP_TERRAIN *lightmap_terrain;
 	BYTE *buffer;
 	BMAP *bmap;
	
	PANEL *panel;
} TX_TERRAIN_LIGHTMAP;

typedef struct TX_OBJECT {
	BYTE *buffer;
	long type;
} TX_OBJECT;

typedef struct TX_BLOCK {
	BLOCK *block;
	VERTEX *vertex;
	TRIANGLE *tris;
	SKIN *skins;
} TX_BLOCK;

typedef struct TX_FILE {
	BYTE *buffer;
	long bufSize;
	char version[5];
	
	//objects
	long objCount;
	TX_OBJECT *objects;
	TX_OBJECT *info;
	
	//blocks
	long blkCount;
	TX_BLOCK *blocks;
	
	//materials
	long mtlCount;
	MATERIAL_INFO *materials;
	
	//textures
	long texCount;
	TX_TEXTURE *textures;
	
	//lightmaps
	long lmCount;
	TX_LIGHTMAP *lightmaps;
	
	//terrain lightmaps
	long tlmCount;
	TX_LIGHTMAP *terrain_lightmaps;
	
} TX_FILE;

// ------------------------------------------------------------

void load_textures (TX_FILE *_txFile) {
	WMB_HEADER *_header = _txFile->buffer;
	
	long *_texOffArray = (long*)(_txFile->buffer + _header->textures.offset);
	_txFile->texCount = *_texOffArray;
	str_printf(strT, "Texture count: %d", _txFile->texCount);
	txt_addstring(txtGlobal, strT);
	txt_addstring(txtGlobal, " ");
	
	_txFile->textures = sys_malloc(sizeof(TX_TEXTURE) * _txFile->texCount);
	
	TX_TEXTURE *_txTex = _txFile->textures;
	long *_texOff = _texOffArray + 1;
	long _index = 0;
	for(; _index < _txFile->texCount; _index += 1, _texOff += 1, _txTex += 1) {
		_txTex->texture = (TEXTURE*)(((BYTE*)_texOffArray) + *_texOff);
		memcpy(_txTex->name, _txTex->texture->name, 16);
		_txTex->width = _txTex->texture->width;
		_txTex->height = _txTex->texture->height;
		_txTex->mipmaps = 0;
		if(_txTex->texture->type - 8 > 0)
			_txTex->mipmaps = 8;
		_txTex->format = _txTex->texture->type - _txTex->mipmaps;
		
		if(_txTex->format == 6) {
			str_cpy(strT, _txTex->texture->name);
			str_cat(strT, ".dds");
			_txTex->buffer = _txTex->texture + 1;
			_txTex->bufSize = _txTex->width;
			add_buffer(strT->chars, _txTex->buffer, _txTex->bufSize);
			_txTex->bmap = bmap_create(strT->chars);
			_txTex->width = bmap_width(_txTex->bmap);
			_txTex->height = bmap_height(_txTex->bmap);
			add_buffer(strT->chars, NULL, _txTex->bufSize);
		} else {
			_txTex->bmap = bmap_createblack(_txTex->width, _txTex->height, texFormats[_txTex->format]);
			bmap_lock(_txTex->bmap, 0);
				_txTex->buffer = _txTex->texture + 1;
				_txTex->bufSize = _txTex->width * _txTex->height * _txTex->bmap->finalbytespp;
				memcpy(_txTex->bmap->finalbits, _txTex->buffer, _txTex->bufSize);
			bmap_unlock(_txTex->bmap);
		}
		
		_txTex->panel = pan_create("flags=SHOW", 1);
		_txTex->panel->pos_x = txtTextures->pos_x;
		_txTex->panel->pos_y = 28 + _index * 45;
		_txTex->panel->bmap = _txTex->bmap;
		_txTex->panel->scale_x = 32.0 / (var)_txTex->width;
		_txTex->panel->scale_y = 32.0 / (var)_txTex->height;
		
		str_printf(strT, "       Name: %s\n       Width:  %d\n       Height: %d\n       Type:   %d + %d", _txTex->name, _txTex->width, _txTex->height, _txTex->format, _txTex->mipmaps);
		txt_addstring(txtTextures, strT);
		txt_addstring(txtTextures, " ");
	}
}

void load_materials (TX_FILE *_txFile) {
	WMB_HEADER *_header = _txFile->buffer;
	
	_txFile->materials = _txFile->buffer + _header->materials.offset;
	_txFile->mtlCount = _header->materials.length / sizeof(MATERIAL_INFO);
	
	str_printf(strT, "Material count: %d", _txFile->mtlCount);
	txt_addstring(txtGlobal, strT);
	txt_addstring(txtGlobal, " ");
	
	MATERIAL_INFO *_mtl = _txFile->materials;
	long _index = 0;
	for(; _index < _txFile->mtlCount; _index += 1, _mtl += 1) {
		str_printf(strT, "Name: %s", _mtl->material);
		txt_addstring(txtMaterials, strT);
		txt_addstring(txtMaterials, " ");
	}
}

void load_info (TX_OBJECT *_txObject, WMB_INFO *_info) {
	_txObject->buffer = _info;
	
	_txObject->type = _info->type;
	txt_addstring(txtObjects, "WMB_INFO");
	
	str_printf(strT, "Sun azimuth: %.3f", (double)_info->azimuth);
	txt_addstring(txtObjects, strT);
	str_printf(strT, "Sun elevation: %.3f", (double)_info->elevation);
	txt_addstring(txtObjects, strT);
	str_printf(strT, "Gamma: %d", _info->gamma);
	txt_addstring(txtObjects, strT);
	
	char *_chrCol = &_info->dwSunColor;
	str_printf(strT, "Sun color: %d, %d, %d, %d", *(_chrCol++), *(_chrCol++), *(_chrCol++), *(_chrCol++));
	txt_addstring(txtObjects, strT);
	str_printf(strT, "Ambient color: %d, %d, %d, %d", *(_chrCol++), *(_chrCol++), *(_chrCol++), *(_chrCol++));
	txt_addstring(txtObjects, strT);
	str_printf(strT, "Fog 1 color: %d, %d, %d, %d", *(_chrCol++), *(_chrCol++), *(_chrCol++), *(_chrCol++));
	txt_addstring(txtObjects, strT);
	str_printf(strT, "Fog 2 color: %d, %d, %d, %d", *(_chrCol++), *(_chrCol++), *(_chrCol++), *(_chrCol++));
	txt_addstring(txtObjects, strT);
	str_printf(strT, "Fog 3 color: %d, %d, %d, %d", *(_chrCol++), *(_chrCol++), *(_chrCol++), *(_chrCol++));
	txt_addstring(txtObjects, strT);
	str_printf(strT, "Fog 4 color: %d, %d, %d, %d", *(_chrCol++), *(_chrCol++), *(_chrCol++), *(_chrCol++));
	txt_addstring(txtObjects, strT);
	
	txt_addstring(txtObjects, " ");
}

void load_position (TX_OBJECT *_txObject, WMB_POSITION *_pos) {
	_txObject->buffer = _pos;
	
	_txObject->type = _pos->type;
	txt_addstring(txtObjects, "WMB_POSITION");
	str_printf(strT, "Origin: %.3f,%.3f,%.3f", (double)_pos->origin[0], (double)_pos->origin[1], (double)_pos->origin[2]);
	txt_addstring(txtObjects, strT);
	
	txt_addstring(txtObjects, " ");
}

void load_light (TX_OBJECT *_txObject, WMB_LIGHT *_light) {
	_txObject->buffer = _light;
	
	_txObject->type = _light->type;
	txt_addstring(txtObjects, "WMB_LIGHT");
	str_printf(strT, "Origin: %.3f,%.3f,%.3f", (double)_light->origin[0], (double)_light->origin[1], (double)_light->origin[2]);
	txt_addstring(txtObjects, strT);
	
	txt_addstring(txtObjects, " ");
}

void load_sound (TX_OBJECT *_txObject, WMB_SOUND *_sound) {
	_txObject->buffer = _sound;
	
	_txObject->type = _sound->type;
	txt_addstring(txtObjects, "WMB_SOUND");
	str_printf(strT, "File: %s", _sound->filename);
	txt_addstring(txtObjects, strT);
	
	txt_addstring(txtObjects, " ");
}

void load_path (TX_OBJECT *_txObject, WMB_PATH *_path) {
	_txObject->buffer = _path;
	
	_txObject->type = _path->type;
	txt_addstring(txtObjects, "WMB_PATH");
	str_printf(strT, "Name: %s", _path->name);
	txt_addstring(txtObjects, strT);
	
	txt_addstring(txtObjects, " ");
}

void load_entity (TX_OBJECT *_txObject, WMB_ENTITY *_ent) {
	_txObject->buffer = _ent;
	
	_txObject->type = _ent->type;
	txt_addstring(txtObjects, "WMB_ENTITY");
	str_printf(strT, "File: %s", _ent->filename);
	txt_addstring(txtObjects, strT);
	
	txt_addstring(txtObjects, " ");
}

void load_old_entity (TX_OBJECT *_txObject, WMB_OLD_ENTITY *_ent) {
	
	_txObject->buffer = _ent;
	
	_txObject->type = _ent->type;
	txt_addstring(txtObjects, "WMB_OLD_ENTITY");
	str_printf(strT, "File: %s", _ent->filename);
	txt_addstring(txtObjects, strT);
	
	txt_addstring(txtObjects, " ");
}

void load_objects (TX_FILE *_txFile) {
	WMB_HEADER *_header = _txFile->buffer;
	
	long *_objOffArray = (long*)(_txFile->buffer + _header->objects.offset);
	_txFile->objCount = *_objOffArray;
	str_printf(strT, "Object count: %d", _txFile->objCount);
	txt_addstring(txtGlobal, strT);
	txt_addstring(txtGlobal, " ");
	
	_txFile->objects = sys_malloc(sizeof(TX_OBJECT) * _txFile->objCount);
	
	TX_OBJECT *_txObject = _txFile->objects;
	long *_objOff = _objOffArray + 1;
	long _index = 0;
	for(; _index < _txFile->objCount; _index += 1, _objOff += 1, _txObject += 1) {
		str_printf(strT, "ID: %d", _index);
		txt_addstring(txtObjects, strT);
		long *_objType = (long*)(((BYTE*)_objOffArray) + *_objOff);
		switch(*_objType) {
			case 1: //WMB_POSITION
				load_position(_txObject, _objType); 
				break;
			case 2: //WMB_LIGHT
				load_light(_txObject, _objType); 
				break;
			case 3: //WMB_OLD_ENTITY
				load_old_entity(_txObject, _objType); 
				break;
			case 4: //WMB_SOUND
				load_sound(_txObject, _objType); 
				break;
			case 5: //WMB_INFO
				_txFile->info = _txObject;
				load_info(_txObject, _objType); 
				break;
			case 6: //WMB_PATH
				load_path(_txObject, _objType); 
				break;
			case 7: //WMB_ENTITY
				load_entity(_txObject, _objType); 
				break;
			default:
				str_printf(strT, "type: %d", *_objType);
				txt_addstring(txtObjects, strT);
				txt_addstring(txtObjects, " ");
				
		}
	}
}

void load_lightmaps (TX_FILE *_txFile) {
	WMB_HEADER *_header = _txFile->buffer;
	
	long _width = 0;
	WMB_INFO *_info = _txFile->info->buffer;
	switch(_info->LMapSize) {
		case 0: _width = 256; break;  // 196608
		case 1: _width = 512; break;  // 786432
		case 2: _width = 1024; break; // 3145728
	}
	long _size = _width * _width * 3;
	_txFile->lmCount = _header->lightmaps.length / _size;
	
	str_printf(strT, "Lightmmap count: %d", _txFile->lmCount);
	txt_addstring(txtGlobal, strT);
	txt_addstring(txtGlobal, " ");
	
	_txFile->lightmaps = sys_malloc(sizeof(TX_LIGHTMAP) * _txFile->lmCount);
	
	TX_LIGHTMAP *_txLm = _txFile->lightmaps;
	BYTE *_buffer = _txFile->buffer + _header->lightmaps.offset;
	long _index = 0;
	for(; _index < _txFile->lmCount; _index += 1, _txLm += 1, _buffer += _size) {
		_txLm->buffer = _buffer;
		
		_txLm->bmap = bmap_createblack(_width, _width, 24);
		
		bmap_lock(_txLm->bmap, 0);
			BYTE *_bits = _txLm->bmap->finalbits;
			BYTE *_pBuf = _txLm->buffer;
			long _y = 0;
			for(; _y < _width; _y += 1) {
				long _x = 0;
				for(; _x < _width; _x += 1, _pBuf += 3, _bits += 4) {
					memcpy(_bits, _pBuf, 3);
					*(_bits + 3) = 255;
				}
			}
		bmap_unlock(_txLm->bmap);
		
		_txLm->panel = pan_create("flags=SHOW", 1);
		_txLm->panel->pos_x = txtLightmaps->pos_x;
		_txLm->panel->pos_y = txtLightmaps->pos_y + txtLightmaps->strings * 9 /*+ _index * 45*/;
		_txLm->panel->bmap = _txLm->bmap;
		_txLm->panel->scale_x = 32.0 / (var)_width;
		_txLm->panel->scale_y = 32.0 / (var)_width;
		
		str_printf(strT, "       ID: %d", _index);
		txt_addstring(txtLightmaps, strT);
		str_printf(strT, "       Width: %d", _width);
		txt_addstring(txtLightmaps, strT);
		str_printf(strT, "       Height: %d", _width);
		txt_addstring(txtLightmaps, strT);
//		txt_addstring(txtLightmaps, " ");
//		txt_addstring(txtLightmaps, " ");
//		txt_addstring(txtLightmaps, " ");
		txt_addstring(txtLightmaps, " ");
		
//		while(!key_space) {
//			DEBUG_BMAP(_txLm->bmap, txtLightmaps->pos_x + 160, 1);
//			wait(1);
//		}
//		key_pressed(-1);
//		wait(1);
		
	}
	
//	str_printf(strT, "%d\n%d", _header->lightmaps.offset, _header->lightmaps.length);
//	txt_addstring(txtLightmaps, strT);
//	txt_addstring(txtLightmaps, " ");
//	
//	str_printf(strT, "%d", _size);
//	txt_addstring(txtLightmaps, strT);
//	txt_addstring(txtLightmaps, " ");
//	
//	str_printf(strT, "LMapSize: %d", _info->LMapSize);
//	txt_addstring(txtLightmaps, strT);
//	txt_addstring(txtLightmaps, " ");
	
//	BMAP *_bmp = bmap_createblack(256, 256, 24);
//	var _frm = bmap_lock(_bmp, 0);
//	memcpy(_bmp->finalbits, _lmOffArray, 256*256*3);
//	bmap_unlock(_bmp);
//	
//	while(!key_space) {
//		DEBUG_BMAP(_bmp, 1, 1);
//		wait(1);
//	}
}

void load_lightmaps_terrain (TX_FILE *_txFile) {
	WMB_HEADER *_header = _txFile->buffer;
	
	long *_tlmOffArray = (long*)(_txFile->buffer + _header->lightmaps_terrain.offset);
	_txFile->tlmCount = *_tlmOffArray;
	str_printf(strT, "Lightmmap terrain count: %d", _txFile->tlmCount);
	txt_addstring(txtGlobal, strT);
	txt_addstring(txtGlobal, " ");
	
	txt_addstring(txtLightmaps, " ");
	txt_addstring(txtLightmaps, "TERRAIN LIGHTMAPS");
	txt_addstring(txtLightmaps, "--------------------");
	txt_addstring(txtLightmaps, " ");
	
	_txFile->terrain_lightmaps = sys_malloc(sizeof(TX_TERRAIN_LIGHTMAP) * _txFile->tlmCount);
	
	TX_TERRAIN_LIGHTMAP *_txLm = _txFile->terrain_lightmaps;
	BYTE *_buffer = _tlmOffArray + 1;
	long _index = 0;
	for(; _index < _txFile->tlmCount; _index += 1, _txLm += 1) {
		_txLm->lightmap_terrain = _buffer;
		_txLm->buffer = _txLm->lightmap_terrain + 1; //_buffer + sizeof(LIGHTMAP_TERRAIN); //
		
		long _size = _txLm->lightmap_terrain->width * _txLm->lightmap_terrain->height * 3;
		
//		if(_index == 1) {
//			_txLm->lightmap_terrain->object = 9;
//		}
		
		_txLm->bmap = bmap_createblack(_txLm->lightmap_terrain->width, _txLm->lightmap_terrain->height, 24);
		bmap_lock(_txLm->bmap, 0);
			BYTE *_bits = _txLm->bmap->finalbits;
			BYTE *_pBuf = _txLm->buffer;
			long _y = 0;
			for(; _y < _txLm->lightmap_terrain->height; _y += 1) {
				long _x = 0;
				for(; _x < _txLm->lightmap_terrain->width; _x += 1, _pBuf += 3, _bits += 4) {
					memcpy(_bits, _pBuf, 3);
					*(_bits + 3) = 255;
				}
			}
		bmap_unlock(_txLm->bmap);
		
		_txLm->panel = pan_create("flags=SHOW", 1);
		_txLm->panel->pos_x = txtLightmaps->pos_x;
		_txLm->panel->pos_y = txtLightmaps->pos_y + txtLightmaps->strings * 9 /*+ _index * 45*/;
		_txLm->panel->bmap = _txLm->bmap;
		_txLm->panel->scale_x = 32.0 / (var)_txLm->lightmap_terrain->width;
		_txLm->panel->scale_y = 32.0 / (var)_txLm->lightmap_terrain->height;
		
		str_printf(strT, "       Object ID: %d", _txLm->lightmap_terrain->object);
		txt_addstring(txtLightmaps, strT);
		str_printf(strT, "       Width: %d", _txLm->lightmap_terrain->width);
		txt_addstring(txtLightmaps, strT);
		str_printf(strT, "       Height: %d", _txLm->lightmap_terrain->height);
		txt_addstring(txtLightmaps, strT);
		txt_addstring(txtLightmaps, " ");
		
		
		
		
		_buffer = _txLm->buffer + _size;
		
//		while(!key_space) {
//			DEBUG_BMAP(_txLm->bmap, 1, 1);
//			wait(1);
//		}
//		key_pressed(-1);
//		wait(1);
	}
	
}

void load_blocks (TX_FILE *_txFile) {
	WMB_HEADER *_header = _txFile->buffer;
	
	long *_blkOffArray = (long*)(_txFile->buffer + _header->blocks.offset);
	_txFile->blkCount = *_blkOffArray;
	str_printf(strT, "Block count: %d", _txFile->blkCount);
	txt_addstring(txtGlobal, strT);
	txt_addstring(txtGlobal, " ");
	
	_txFile->blocks = sys_malloc(sizeof(TX_BLOCK) * _txFile->blkCount);
	
	TX_BLOCK *_txBlock = _txFile->blocks;
	BYTE *_buffer = _blkOffArray + 1;
	long _index = 0;
	for(; _index < _txFile->blkCount; _index += 1, _txBlock += 1) {
		_txBlock->block = _buffer;
		_buffer += sizeof(BLOCK);
		
		_txBlock->vertex = _buffer;
		_buffer += sizeof(VERTEX) * _txBlock->block->lNumVerts;
		
		_txBlock->tris = _buffer;
		_buffer += sizeof(TRIANGLE) * _txBlock->block->lNumTris;
		
		_txBlock->skins = _buffer;
		_buffer += sizeof(SKIN) * _txBlock->block->lNumSkins;
		
		str_printf(strT, "ID: %d", _index);
		txt_addstring(txtBlocks, strT);
		str_printf(strT, "Vertex: %d", _txBlock->block->lNumVerts);
		txt_addstring(txtBlocks, strT);
		str_printf(strT, "Triangles: %d", _txBlock->block->lNumTris);
		txt_addstring(txtBlocks, strT);
		str_printf(strT, "Skins: %d", _txBlock->block->lNumSkins);
		txt_addstring(txtBlocks, strT);
		txt_addstring(txtBlocks, " ");
	}
	
}

TX_FILE *load_level_file (char *_levelName) {
	if(!file_exists(_levelName)) {
		printf("file not found\n%s", _levelName);
		return NULL;
	}
	
	// main data struct
	TX_FILE *_txFile = sys_malloc(sizeof(TX_FILE));
	memset(_txFile, 0, sizeof(TX_FILE));
	
	// open file
	_txFile->buffer = file_load(_levelName, NULL, &_txFile->bufSize);
	
	// header
	WMB_HEADER *_header = _txFile->buffer;
	
	// version
	memcpy(_txFile->version, _header->version, 4);
	_txFile->version[4] = NULL;
	str_printf(strT, "Format version: %s", _txFile->version);
	txt_addstring(txtGlobal, strT);
	txt_addstring(txtGlobal, " ");
	if(_txFile->version[3] != 55) {
		txt_addstring(txtGlobal, "wrong wmb version");
		return _txFile;
	}
	
	// objects
	load_objects(_txFile);
	
	// blocks
	load_blocks(_txFile);
	
	// materials
	load_materials(_txFile);
	
	// textures
	load_textures(_txFile);
	
	// lightmaps
	load_lightmaps(_txFile);
	wait_for(load_lightmaps);
	
	// lightmaps terrain
	load_lightmaps_terrain(_txFile);
	
	
	
	txt_addstring(txtGlobal, "--------------------");
	txt_addstring(txtGlobal, " ");
	
	str_printf(strT, "objects:    %d - %d", _header->objects.offset, _header->objects.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "legacy7:    %d - %d", _header->legacy7.offset, _header->legacy7.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "legacy1:    %d - %d", _header->legacy1.offset, _header->legacy1.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "blocks:     %d - %d", _header->blocks.offset, _header->blocks.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "materials:  %d - %d", _header->materials.offset, _header->materials.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "textures:   %d - %d", _header->textures.offset, _header->textures.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "palettes:   %d - %d", _header->palettes.offset, _header->palettes.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "lightmaps:  %d - %d", _header->lightmaps.offset, _header->lightmaps.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "terrain lm: %d - %d", _header->lightmaps_terrain.offset, _header->lightmaps_terrain.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "bsp_leafs:  %d - %d", _header->bsp_leafs.offset, _header->bsp_leafs.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "bsp_nodes:  %d - %d", _header->bsp_nodes.offset, _header->bsp_nodes.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "aabb_hulls: %d - %d", _header->aabb_hulls.offset, _header->aabb_hulls.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "bsp_blocks: %d - %d", _header->bsp_blocks.offset, _header->bsp_blocks.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "pvs:        %d - %d", _header->pvs.offset, _header->pvs.length);
	txt_addstring(txtGlobal, strT);
	str_printf(strT, "            %d", _header->pvs.offset + _header->pvs.length);
	txt_addstring(txtGlobal, strT);
	



	str_printf(strT, "legacy2:    %d - %d", _header->legacy2.offset, _header->legacy2.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "legacy3:    %d - %d", _header->legacy3.offset, _header->legacy3.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "legacy4:    %d - %d", _header->legacy4.offset, _header->legacy4.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "legacy5:    %d - %d", _header->legacy5.offset, _header->legacy5.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "legacy6:    %d - %d", _header->legacy6.offset, _header->legacy6.length);
	txt_addstring(txtGlobal, strT);
	
	str_printf(strT, "legacy8:    %d - %d", _header->legacy8.offset, _header->legacy8.length);
	txt_addstring(txtGlobal, strT);
	
	txt_addstring(txtGlobal, " ");
	
	return _txFile;
}

void txFile_remove (TX_FILE *_txFile) {
	
//	TX_TEXTURE *_txTex = _txFile->textures;
//	long _index = 0;
//	for(; _index<_txFile->texCount; _index+=1, _txTex+=1) {
//		pan_remove(_txTex->panel);
//		bmap_remove(_txTex->bmap);
//	}
//	sys_free(_txFile->textures);
	
	file_load(NULL, _txFile->buffer, &_txFile->bufSize);
}

void main () {
	video_mode = 10;
	wait(3);
	on_esc = NULL;
	level_load("");
	camera->bg = pixel_for_vec(vector(0,0,0), 100, 888);
	
	TX_FILE *_txFile = load_level_file("scene.wmb");
	
	while(!key_esc) {
		wait(1);
	}
	
	file_save("scene_mod.wmb", _txFile->buffer, _txFile->bufSize);
	
	txFile_remove(_txFile);
	
	sys_exit(NULL);
}


Have fun!

Last edited by txesmi; 12/31/20 07:54.
Re: Open/Extract Model and Textures from WMB [Re: txesmi] #482133
12/30/20 16:20
12/30/20 16:20
Joined: Dec 2020
Posts: 3
M
MooseMannequin Offline OP
Guest
MooseMannequin  Offline OP
Guest
M

Joined: Dec 2020
Posts: 3
Uuuuuh, what exactly should I do with this terrifying tree?
I read info in the link, at least now I know that, .WMB created in WED. I already tried import my .WMB there, it just says: "invalid file name" and that's it. But even if it'll open, I still don't get how to extract the model from .WMB.
I thought, it's gonna be something like .OBJ or other 3D type file haha. If it's gonna be the code, I have no use of it then. I need visual model.

And I made mistake, I said, that .WMB has model and textures. .WMB has the model only, the textures in .WTB files.
Thanks

Re: Open/Extract Model and Textures from WMB [Re: MooseMannequin] #482134
12/30/20 16:36
12/30/20 16:36
Joined: May 2005
Posts: 868
Chicago, IL
Dooley Offline
User
Dooley  Offline
User

Joined: May 2005
Posts: 868
Chicago, IL
A WMB file is a game level, so it will contain 3D models as well as textures. However, WMB is the compiled level, not the editable level you would work on designing. I misread this part, and assumed you meant WMP, which is the editable level.

As WMB, it would be much more difficult to extract models and textures from it. txesmi's script, if I understand it correctly, would allow you to open a WMB and extract models/textures as you need, but if you are not familiar with how the engine works, and how to run scripts, then that might look intimidating.

Re: Open/Extract Model and Textures from WMB [Re: MooseMannequin] #482135
12/30/20 18:31
12/30/20 18:31
Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
Quad Online
Senior Expert
Quad  Online
Senior Expert

Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
Only level blocks are actually in the wmb file. Models/textures are separate files with the extension .mdl.
Models may be compressed in wrs though.


3333333333
Re: Open/Extract Model and Textures from WMB [Re: Dooley] #482136
12/30/20 20:23
12/30/20 20:23
Joined: Dec 2020
Posts: 3
M
MooseMannequin Offline OP
Guest
MooseMannequin  Offline OP
Guest
M

Joined: Dec 2020
Posts: 3
I understand, well, I can run scripts on "copy/paste, press Run" level haha, but I definitely not familiar with engines,
So, I think, I will try do this through Unity, but again I need to figure out how to use Python there, instead of C#, because the script WMB2OBJ that I found, written on Python language.


Moderated by  HeelX, rvL_eXile 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1