XeNTaX Forum Index
Forum MultiEx Commander Tools Tools Home
It is currently Sun Mar 26, 2017 2:45 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: Make_obj (C source)
PostPosted: Mon Mar 06, 2017 11:01 am 
Offline
M-M-M-Monster veteran
M-M-M-Monster veteran
User avatar

Joined: Fri Apr 20, 2012 9:24 am
Posts: 1954
Has thanked: 342 times
Have thanks: 951 times














You can make the ads go away by registering

well, another year has come and gone and I think it's time to share some source (based on my Make_H2O project).

This project shall help to extract multi mesh models so is some kind of follow up to hex2obj.
You don't need to use hex2obj for analysing the model before (but it's recommended).

You can't make too much use of this project if you don't understand 'C', though.
(btw: it doesn't contain the Make_H2O_ForzaHor3 source, if you thought of that. Just some basic functions.)

I used the Han_stormtrooper.rax model as a startup which can be found here:
viewtopic.php?f=16&t=13867&p=126467&hilit=stormtrooper#p126467
(Thx to AceWell) :)

I've tested this one character model only so might not work for other characters
and will NOT work for objects, I guess. Feel free to expand the code to do so.

The FVFsize is fixed; you might use the editbox to support different sizes (not implemented so far).

I'm a great fan of pattern searching so here we go:

Find the counts (behind pattern 00 00 10 03, so search for that first)
find first "FACE " (46 41 43 45 00) after uvs
then find "pos ", get verts and uvs startaddress

and skip to the face indices table

--------------------------

I'm pretty sure we'll need some data alignment here (function DWORD dataAlignment(DWORD j) for example)
instead of simply adding 40 bytes here to skip to the face indices table:

pFBuf= pTmp + addrUV + 40 ; j= addrUV + 40 ; fprintf( stream, "# start of FIs: %x\n", j) ;
(where addrUV is the last uv's address +1)

https://www.pic-upload.de/view-32802746 ... r.jpg.html


here's the "main" function of the code, it's ugly and simple, but it works:
Code:
void SM_of_SW_BF3_loop(HWND hwnd, char szPathname[], DWORD dwStart)      // scanning the submeshes
{                                                                         // only one model tested
   char * pFBuf, *pTmp, szNo[4] ;
   BYTE cnt, fCnt=0, i, SMcnt, FVFsize= 24 ;
   int k, nValue[16] ;
   WORD FI[3] ;
   DWORD FIcnt, FIcnt_arr[999], vCnt, vCnt_arr[999] ;         //
   DWORD addrUV, addrV, j=0, jOld, lastJ, offs2 ;  //
   DWORD minFaceInd = 16777215, maxFaceInd = 0, lastFaceInd=0 ;

   pFBuf = (char *) lpFBuf ; pTmp= pFBuf ;
   pFBuf += dwStart ;
   SendMessage(GetDlgItem(hwnd, ID_LIST), LB_ADDSTRING, 0, (LPARAM) " creating obj:") ;
   cnt= 0 ; lastJ= 0 ; j= 0 ;
   // get counts of submeshes
   nValue[0]= 0; nValue[1]= 0; nValue[2]= 0x10; nValue[3]= 3;    // there's counts behind that pattern
   do {
        offs2 = FindBytes(lpFBuf, j, dwFileSize-j, nValue, 4) ;       // j is offset here
        if (offs2!=0) {
            pFBuf += offs2 + 4 ; j += offs2 + 4 ;
            GetDW(pFBuf, j, vCnt, true) ; GetDW(pFBuf, j, FIcnt, true) ; // j not used here
            vCnt_arr[cnt]= vCnt ; FIcnt_arr[cnt]= FIcnt ; fprintf( stream, "# %d %d\n", vCnt, FIcnt) ;
            if (cnt<999) cnt++ ; else chMB("Too many submeshes!") ;
            pFBuf += 8 ; j += 8 ;
        }
   } while ((offs2!=0)&&(j<dwFileSize)) ;
    // get counts of last submesh
   offs2 = FindBytes(lpFBuf, j, dwFileSize-j, nValue, 3) ;       // j is offset here
    if (offs2!=0) {
        pFBuf += offs2 + 4 ; j += offs2 + 4 ;
        GetDW(pFBuf, j, vCnt, true) ; GetDW(pFBuf, j, FIcnt, true) ; // j not used here
        vCnt_arr[cnt]= vCnt ; FIcnt_arr[cnt]= FIcnt ; fprintf( stream, "# %d %d\n", vCnt, FIcnt) ;
        pFBuf += 8 ; j += 8 ; cnt++ ;
    } else chMB("Error, last submesh not found!") ;
    // where's the stzartaddresses for vertices and uvs?
   nValue[0]= 0x46; nValue[1]= 0x41; nValue[2]= 0x43; nValue[3]= 0x45; nValue[4]= 0;    // 'FACE'
   offs2 = FindBytes(lpFBuf, j, dwFileSize-j, nValue, 5) ;       // j is offset here
    if (offs2!=0) {
        pFBuf += offs2 ; j += offs2 ;
        pFBuf += 8 ; j += 8 ;
    } else chMB("Error, 'FACE ' after last counts not found!") ;    // evtl. erste von 2 'FACE'
   nValue[0]= 0x50; nValue[1]= 0x4F; nValue[2]= 0x53; nValue[3]= 0;     // 'POS '
   offs2 = FindBytes(lpFBuf, j, dwFileSize-j, nValue, 4) ;       // j is offset here
    if (offs2!=0) {
        pFBuf += offs2 -32 ; j += offs2 - 32 ;                   //
        GetDW(pFBuf, j, addrV, true) ; pFBuf += 16 ; j += 16 ;
        GetDW(pFBuf, j, addrUV, true) ; fprintf( stream, "# %x %x\n", addrV, addrUV) ;
        pFBuf += 72 ; j += 72 ;
    } else chMB("Error, 'POS ' after 'FACE' not found!") ;
    if (j!=addrV) {chMB("address calculation went wrong! break...") ; return ;}
    SMcnt= cnt ;
    for (i=0;i < SMcnt;i++) {
        fprintf( stream, "# %x, %d\n", addrV, vCnt_arr[i]) ;
        log_short_Verts(addrV, vCnt_arr[i], FVFsize) ; addrV += FVFsize*vCnt_arr[i] ;
    }
    if (addrV!=addrUV) {chMB("UV address calculation went wrong! break...") ; return ;}
    // go for uvs, blocksize is 4
    for (i=0;i < SMcnt;i++) {
        log_short_UVs(addrUV, vCnt_arr[i], 4) ; addrUV += 4*vCnt_arr[i] ;
    }
    pFBuf= pTmp + addrUV + 40 ; j= addrUV + 40 ; fprintf( stream, "# start of FIs: %x\n", j) ;
    // go for face indices
    for (i=0;i < SMcnt;i++) {
        _itoa(i, szNo, 10) ; fprintf( stream, "g SM_%s\n", szNo) ;      // separating the submeshes (building groups)
        for (k=0;k<FIcnt_arr[i];k++) {       //
            //                       adding lastFaceInd in that function to get absolute FIs
            FI[fCnt]= (WORD) GetFaceIndexBigE(pFBuf, j, minFaceInd, maxFaceInd, lastFaceInd, false) ;   //
            fCnt++ ;
            if (fCnt==3) {
                fCnt=0 ;                        //
                fprintf( stream, "f %d/%d %d/%d %d/%d\n", FI[0],FI[0],FI[1],FI[1],FI[2],FI[2]) ;
            }
        }
        if (maxFaceInd<lastFaceInd) {
            fprintf( stream, "error! maxFI %d < lastFI %d\n\n", maxFaceInd, lastFaceInd) ;
        }
        else lastFaceInd = maxFaceInd ;         // needed to "convert" relative to absolute face indices
        fprintf( stream, "# next FI block: %x\n", j) ;
    }
}
(code doesn't care for normals)


Attachments:


You do not have the required permissions to view the files attached to this post. Register to gain access.


_________________
Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
Make_H2O-ForzaHor3-jm8.zip

"We are Microsoft. You will be assimilated. Resistance is Futile."


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: Yahoo [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group