MESH_VERTEXDATA to MSH.XML 엘더스크롤&NWN&DA

/* 드래곤에이지의 원본 MSH 파일의 MESH_VERTEXDATA를 txt파일로 추출한 뒤, 필요로 하는
TANGENT,BINORMAL,NORMAL 값을 XML 포맷으로 추출하기 위한 C프로그래밍. C언어는 FLOAT4 형식을 지원하지 않기 때문에 추출하는 과정이 귀찮다. FLOAT4 추출 소스는 http://blog.naver.com/sdragoon?Redirect=Log&logNo=150075802753

실행 예) mshxml_export.exe "df_arm_nud_0.txt" "_DF_ARM_NUD_MSH_TARGET.txt"

여기서 df_arm_nud_0.txt는 드래곤에이지 툴킷을 통해 추출한 MESH_VERTEXDATA의 파일명 */

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
float HALFToFloat(unsigned short);
unsigned short floatToHALF(float);
unsigned int halfToFloatI(unsigned short);
unsigned short floatToHalfI(unsigned int);
float HALFToFloat(unsigned short y)
{
union {
float f;
unsigned int i;
} v;
v.i = halfToFloatI(y);
return v.f;
}

unsigned int halfToFloatI(unsigned short y)
{
int s = (y >> 15) & 0x00000001; // sign
int e = (y >> 10) & 0x0000001f; // exponent
int f = y & 0x000003ff; // fraction
// need to handle 7c00 INF and fc00 -INF?
if (e == 0)
{
// need to handle +-0 case f==0 or f=0x8000?
if (f == 0) // Plus or minus zero
return s << 31;
else { // Denormalized number -- renormalize it
while (!(f & 0x00000400))
{
f <<= 1;
e -= 1;
}
e += 1;
f &= ~0x00000400;
}
}
else if (e == 31)
{
if (f == 0) // Inf
return (s << 31) | 0x7f800000;
else // NaN
return (s << 31) | 0x7f800000 | (f << 13);
}
e = e + (127 - 15);
f = f << 13;
return ((s << 31) | (e << 23) | f);
}
unsigned short floatToHALF(float i)
{
union { float f; unsigned int i; } v;
v.f = i;
return floatToHalfI(v.i);
}
unsigned short floatToHalfI(unsigned int i)
{
register int s = (i >> 16) & 0x00008000; // sign
register int e = ((i >> 23) & 0x000000ff) - (127 - 15); // exponent
register int f = i & 0x007fffff; // fraction
// need to handle NaNs and Inf?
if (e <= 0)
{
if (e < -10)
{
if (s) // handle -0.0
return 0x8000;
else
return 0;
}
f = (f | 0x00800000) >> (1 - e);
return s | (f >> 13);
}
else if (e == 0xff - (127 - 15))
{
if (f == 0) // Inf
return s | 0x7c00;
else { // NAN
f >>= 13;
return s | 0x7c00 | f | (f == 0);
}
}
else
{
if (e > 30) // Overflow
return s | 0x7c00;
return s | (e << 10) | (f >> 13);
}
}

int main(int argc, char *argv[])
{
float , f2;
unsigned short h;

FILE *IN,*OUT;
char str[4],hex[7];
char TEST[255];
int ch;
int xy,ww;
int xx,yy,zz = 0;

if ( ( IN = fopen( argv[1], "r" ) ) == NULL ) return 0;
if ( ( OUT = fopen( argv[2], "w" ) ) == NULL ) return 0;

fputs("<Data ElementCount=\"9999\" Semantic=\"TANGENT\" Type=\"Float4\">\n<![CDATA[", OUT);    

for (xy=0;xy<3;xy++)
{
zz = 0;
ww = 1;
fseek(IN,0,SEEK_SET);
for(xx=0;;xx++)
{
if((ch = fgetc(IN)) == EOF ) break;
if(!isspace(ch))
{
if(yy%4 == 0) str[2] = ch;
if(yy%4 == 1) str[3] = ch;
if(yy%4 == 2) str[0] = ch;
if(yy%4 == 3) str[1] = ch;
yy++;
}
if((xx % 6 == 4) && (yy % 4 == 0))
{
zz++;
if ( zz == 29 ) {
zz = 1;
ww++;
}
if ( zz == 7 ) {
if ( xy == 0 ) fputs("\n", OUT); // tangent
zz = 9;
}
if ((zz == 13) && (xy == 1)) fputs("\n", OUT); // binormal
if ((zz == 17) && (xy == 2)) fputs("\n", OUT); // normal

//core
if ( zz >= 9 && zz < 21 ) {
h = strtol(str,NULL,16);
f2 = HALFToFloat(h);
sprintf(TEST,"%f",f2);
if ((zz <13) && (xy == 0)) fputs(TEST, OUT);
if ((zz >=13 && zz < 17)&& (xy == 1)) fputs(TEST, OUT);
if ((zz >=17) && (xy == 2)) fputs(TEST, OUT);
fputs(" ", OUT);
}
yy = yy % 4;
//..
}
}

fputs("\n]]>\n
\n", OUT);

sprintf(TEST,"%d",ww);
if ( xy == 0 ) {
fputs(" fputs(TEST,OUT);
fputs("\" Semantic=\"BINORMAL\" Type=\"Float4\">\n<![CDATA[", OUT);    

fseek(OUT,20,SEEK_SET);
fputs(TEST,OUT);
fseek(OUT,0,SEEK_END);
}
if ( xy == 1 ) {
fputs("<Data ElementCount=\"", OUT);         
fputs(TEST,OUT);         
fputs("\" Semantic=\"NORMAL\" Type=\"Float4\">\n<![CDATA[", OUT);        
}
}

fclose(IN);
fclose(OUT);

// system("PAUSE");
return 0;
}

덧글

댓글 입력 영역