Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.

Ragnarok Online

Featured Replies

  • Author
  • Localization

CriticalError, posted Sat Sep 13, 2014 2:53 am (481)


Hello guys, well today I install this game, I unpack files and got some files with a lot extentions, like:

-RSW
-RSM
-GAT
-LUB
-BMP

a lot more, so well my question is if somebody cna take a look into 3D model format? ok many thanks for all and hope somebody can make a something with samples, grateful for support.

http://puu.sh/bwKuO/499ef702f2.jpg

ok and here some info about files.

Quote:
- texture paths are relative to the Ragnarok folder.
- size specified as structure or data type or in bytes
- structure sizes and content listed in type definitions below

Data/Field Size Notes
======================================================================================

--------------------------------------------------------------------------------------
'GRSM' 4 RSM identifier/header
todo 27 Unknown, labled "todo"
nTextures int Number of textures (int)
text_name ro_string * nTextures

Keep reading in a mesh until EOF or
30 meshes are read in
---------------------------------------------------------------------------------------
name ro_string name of mesh
todo int integer, only read for first mesh
parent_name ro_string
ftodo int * 10 Array of 10 floats, only read for first mesh
ntextures int number of textures for this mesh
n int * ntextures see code
transf float * 22 used in transformations...

npos_vtx int number of vertices
pos_vtx ro_vertex_t * npos_vtx array of vertices

ntex_vtx int number of texture coordinates
tex_vtx ro_vertex_t * ntex_vtx array of coordinates (see code)

nall_faces int number of faces
all_faces ro_face_t * nall_faces array of face structures

nframes int number of frame animations
frames ro_frame_t * nframes array of frame structures


So RSM layout is:



.
.
.


or usually just one mesh



Here's the code:
================
//Type definitions

typedef char ro_string_t[40]; // The RO path string, 40 bytes wide

typedef struct { // RSM Header
char filecode[4];
char todo[27];
} rsm_header_t;

typedef struct { // Used by app to store position information
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat rx;
GLfloat ry;
GLfloat rz;
GLfloat sx;
GLfloat sy;
GLfloat sz;
} ro_position_t;

typedef float ro_vertex_t[3]; // Stores vertex information

typedef struct {
short v[3]; // Indexed vertices to use for this face
short t[3]; // Indexed texture coordinates to use for this face
unsigned short text; // Which texture to use for this surface
unsigned short todo1; // ???
unsigned int todo2; // ???
unsigned int nsurf; // ???
} ro_face_t;

typedef struct {
unsigned int text; // Which texture to use for this surface
int nvertex; // Number of Vertexes
int nfaces; // Number of Faces/Triangles
gl_vertex_t *vertex;
gl_face_t *faces;
} ro_surface_t;

typedef struct {
GLfloat todo[22]; // ???
} ro_transf_t;

typedef float ro_quat_t[4];

typedef struct {
int time;
ro_quat_t orientation;
} ro_frame_t;

typedef struct {
GLfloat max[3];
GLfloat min[3];
GLfloat range[3];
} bounding_box_t;

//Classes
class RSM
{
public:
RSM(); // Constructor
bool Load(char *ragnapath, char *filename); // RSM Loader
void Display(ro_position_t pos);
void DisplayMesh(bounding_box_t *b, int n, ro_transf_t *ptransf=NULL);
virtual ~RSM();

private:
void BoundingBox();

private:
bounding_box_t box;
int *father;
GLfloat range[3];
GLfloat min[3];
GLfloat max[3];
rsm_header_t header;
int nmeshes;
RSM_Mesh *meshes;
int ntextures;
GLuint *textures;
ro_string_t *textures_name;
bool *alphatex;
};


class RSM_Mesh
{
public:
RSM_Mesh();
bool Load(FILE *fp, GLuint *all_textures, bool *alphatex, bool main);
void Display(bounding_box_t *box, ro_transf_t *ptransf = NULL);
virtual ~RSM_Mesh();
ro_transf_t transf;
ro_vertex_t *pos_vtx;
GLfloat range[3];
GLfloat min[3];
GLfloat max[3];
void BoundingBox(ro_transf_t *ptransf=NULL);
ro_string_t name;
ro_string_t parent_name;
bool only;

private:


//Parsing
bool RSM::Load(char *ragnapath, char *filename)
{
FILE *fp;
int i;

fp = fopen(filename, "rb");

if (!fp) {
return false;
}

//Read in the header
fread (&header, sizeof(rsm_header_t), 1, fp);

//Get the number of textures
fread (&ntextures, sizeof(int), 1, fp);

textures = new GLuint[ntextures];
alphatex = new bool[ntextures];
textures_name = new ro_string_t[ntextures];

//Read texture paths into an array of strings 40 bytes wide each...
fread (textures_name, sizeof(ro_string_t), ntextures, fp);

//prepare textures for openGL
glGenTextures(ntextures, textures);

//Load textures
for (i = 0; i < ntextures; i )
LoadTexture (ragnapath, textures_name[i], textures[i], &alphatex[i]);

meshes = new RSM_Mesh[30];

//Read in mesh structure until we hit end-of-file or 30 meshes
while (file_status(fp) != 0) {
meshes[nmeshes].Load(fp, textures, alphatex, (nmeshes == 0));
nmeshes ;
if (nmeshes > 29)
break;
}

if (nmeshes == 1)
meshes[0].only = true; //Set if only one mesh was read...
else
meshes[0].only = false;
fclose (fp);

//create mesh heirarchy
father = new int[nmeshes];
father[0] = 0;
for (i = 0; i < nmeshes; i )
for (int j = 0; j < nmeshes; j )
if ((j != i) && (!strcmp(meshes[j].parent_name, meshes[i].name)))
father[j] = i;

BoundingBox(); //Set up bounding box

return true;
}



AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL;

if (!Filename)
{
return NULL;
}

File=fopen(Filename,"r");

if (File)
{
fclose(File);
return auxDIBImageLoad(Filename);
}

return NULL;
}

#define coord3(t, x, y, o) t[3*((x) (y)*w) o]
#define coord4(t, x, y, o) t[4*((x) (y)*w) o]

bool LoadTexture(char *ragnapath, char *filename, GLuint texture, bool *alpha)
{
int h, w, j, k;
unsigned char *cdata;
unsigned char *ndata;
char buffer[512];
int l;
l = strlen(filename);

sprintf (buffer, "%s\\data\\texture\\%s", ragnapath, filename);

if ((filename[l-3] == 'b' &&
filename[l-2] == 'm' &&
filename[l-1] == 'p') || (filename[l-3] == 'B' &&
filename[l-2] == 'M' &&
filename[l-1] == 'P')) {

AUX_RGBImageRec *image;
image = LoadBMP(buffer);
if(!image) image = LoadBMP("blank.bmp");
h = image->sizeY;
w = image->sizeX;

cdata = (unsigned char *) image->data;
ndata = (unsigned char *) malloc (sizeof(unsigned char)*4*h*w);

for (j = 0; j < h; j )
for (k = 0; k < w; k ) {
unsigned char a, r, g, b;

b = coord3(cdata, k, h-1-j, 0);
g = coord3(cdata, k, h-1-j, 1);
r = coord3(cdata, k, h-1-j, 2);

ndata[4*(j*w k)] = b;
ndata[4*(j*w k) 1] = g;
ndata[4*(j*w k) 2] = r;
if (g==0 && r>253 && b>253)
ndata[4*(j*w k) 3] = 0;
else
ndata[4*(j*w k) 3] = 255;
}

glBindTexture(GL_TEXTURE_2D, texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

gluBuild2DMipmaps ( GL_TEXTURE_2D, GL_RGBA, w, h,
GL_RGBA, GL_UNSIGNED_BYTE, ndata );

if (alpha)
*alpha = false;
} else if ((filename[l-3] == 't' &&
filename[l-2] == 'g' &&
filename[l-1] == 'a') || (filename[l-3] == 'T' &&
filename[l-2] == 'G' &&
filename[l-1] == 'A')) {


image_t p;

glBindTexture(GL_TEXTURE_2D, texture);
tgaLoad ( buffer, &p, TGA_NO_PASS);

h = p.info.height;
w = p.info.width;

cdata = (unsigned char *) p.data;
ndata = (unsigned char *) malloc (sizeof(unsigned char)*4*h*w);

for (j = 0; j < h; j )
for (k = 0; k < w; k ) {
unsigned char a, r, g, b;

r = coord4(cdata, k, h-1-j, 0);
g = coord4(cdata, k, h-1-j, 1);
b = coord4(cdata, k, h-1-j, 2);
a = coord4(cdata, k, h-1-j, 3);

ndata[4*(j*w k)] = r;
ndata[4*(j*w k) 1] = g;
ndata[4*(j*w k) 2] = b;
ndata[4*(j*w k) 3] = a;
}

char buf[512];
sprintf(buf, "%d\n", p.info.tgaColourType);
// MessageBox(NULL, buf, NULL, 0);

glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

gluBuild2DMipmaps ( GL_TEXTURE_2D, p.info.tgaColourType, p.info.width,
p.info.height, p.info.tgaColourType, GL_UNSIGNED_BYTE, ndata );

if (alpha)
*alpha = true;
} else {
MessageBox (NULL, "Unknown texture type", "Error", 0);
return false;
}

return true;
}


bool RSM_Mesh::Load(FILE *fp, GLuint *all_textures, bool *all_alphatex, bool main)
{
int i;
char buffer[1024];
int *surfnum;
FILE *fout;

//Get the name of this mesh
fread (name, sizeof(ro_string_t), 1, fp);

if (main)
fread (&todo, sizeof(int), 1, fp);

fread (parent_name, sizeof(ro_string_t), 1, fp);

if (main)
fread (ftodo, sizeof(float), 10, fp);

fread (&ntextures, sizeof(int), 1, fp);

textures = new GLuint[ntextures];
alphatex = new bool[ntextures];
which = new int[ntextures];

for (i = 0; i < ntextures; i ) {
int n;
fread (&n, sizeof(int), 1, fp);
which[i] = n;
textures[i] = all_textures[n];
alphatex[i] = all_alphatex[i];
}

fread (&transf, sizeof(ro_transf_t), 1, fp);

fread (&npos_vtx, sizeof(int), 1, fp);
pos_vtx = new ro_vertex_t[npos_vtx];
fread (pos_vtx, sizeof(ro_vertex_t), npos_vtx, fp);

fread (&ntex_vtx, sizeof(int), 1, fp);
tex_vtx = new ro_vertex_t[ntex_vtx];
fread(tex_vtx, sizeof(ro_vertex_t), ntex_vtx, fp);

fread(&nall_faces, sizeof(int), 1, fp);
all_faces = new ro_face_t[nall_faces];
fread (all_faces, sizeof(ro_face_t), nall_faces, fp);

if (file_status(fp) != 2) {
return true;
}

fread (&nframes, sizeof(int), 1, fp);
frames = new ro_frame_t[nframes];
fread (frames, sizeof(ro_frame_t), nframes, fp);

return true;
}



void RSM_Mesh::BoundingBox(ro_transf_t *ptransf)
{
int main = (ptransf == NULL);
GLfloat Rot[16];
GLfloat *Transf;
int i;
int j;
int k;
GLfloat pmax[3], pmin[3];

Rot[0] = transf.todo[0];
Rot[1] = transf.todo[1];
Rot[2] = transf.todo[2];
Rot[3] = 0.0;

Rot[4] = transf.todo[3];
Rot[5] = transf.todo[4];
Rot[6] = transf.todo[5];
Rot[7] = 0.0;

Rot[8] = transf.todo[6];
Rot[9] = transf.todo[7];
Rot[10] = transf.todo[8];
Rot[11] = 0.0;

Rot[12] = 0.0;
Rot[13] = 0.0;
Rot[14] = 0.0;
Rot[15] = 1.0;

max[0] = max[1] = max[2] = -999999.0;
min[0] = min[1] = min[2] = 999999.0;

for (i = 0; i < npos_vtx; i ) {
GLfloat vtemp[3], vout[3];

MatrixMultVect(Rot, pos_vtx[i], vout);
for (j = 0; j < 3; j ) {
GLfloat f;
if (!only)
f = vout[j] transf.todo[12 j] transf.todo[9 j];
else
f = vout[j];

min[j] = MIN(f, min[j]);
max[j] = MAX(f, max[j]);
}
}

for (j=0; j < 3; j )
range[j] = (max[j] min[j])/2.0;
}


http://puu.sh/bwK4O/f0d23504d0.7z
Guest
This topic is now closed to further replies.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.