Всем привет. Я тут на днях скитался по интернету и искал загрузчик SMD моделей от Half-Life 1, но так и не нашёл... Решил вот сделать своими руками, может кому понадобится :)
SMD.H
struct SMDNode{ char nodename[32]; int parent; }; struct SMDFrame{ int nodeid; float px,py,pz; float rx,ry,rz; }; struct SMDVertex{ char texturename[32]; int nodeid; float px,py,pz; float nx,ny,nz; float u,v; }; class SMD{ private: int numnodes; int numframes; int numtimes; int numvertices; int timehelpid; int verthelpid; SMDNode *pNodes; SMDFrame **pFrames; SMDVertex *pVertices; public: bool LoadSmdFromFile(char *File); void Release( void); int GetNumNodes( void); int GetNumFrames( void); int GetNumTimes( void); int GetNumVertices( void); SMDNode GetNode( int IndexNode); SMDFrame GetFrame( int IndexTime,int IndexFrame); SMDVertex GetVertex( int IndexVertex); int FindNextNode( int Id); };
SMD.CPP
bool SMD::LoadSmdFromFile(char *File){ numnodes = 0; numframes = 0; numtimes = 0; numvertices = 0; timehelpid = -1; verthelpid = 0; pNodes = NULL; pFrames = NULL; pVertices = NULL; bool is_nodes = false; bool is_triangles = false; bool is_end = false; string buff; ifstream smd( File); if( !smd){ return false; } while( getline( smd,buff)){ strtok( ( char*)buff.c_str( )," "); if( strcmp( buff.c_str( ),"nodes")==0){ is_nodes = true; } if( strcmp( buff.c_str( ),"time")==0){ numtimes++; } if( strcmp( buff.c_str( ),"triangles")==0){ is_triangles = true; } if( strcmp( buff.c_str( ),"end")==0){ if( is_nodes){ is_nodes = false; } if( is_triangles){ is_triangles = false; } } if( is_nodes){ numnodes++; } if( is_triangles){ static int x = 0; if( x < 3){ numvertices++; } x++; if( x > 3){ x = 0; } } } numnodes--; numvertices--; numframes = numnodes; pNodes = new SMDNode[numnodes]; pFrames = new SMDFrame*[numtimes]; for( int i = 0;i<numtimes;i++){ pFrames[i] = new SMDFrame[numnodes]; } pVertices = new SMDVertex[numvertices]; smd.close( ); is_nodes = false; is_triangles = false; is_end = false; ifstream smd2( File); if( !smd2){ return false; } while( getline( smd2,buff)){ string buff2 = buff; strtok( ( char*)buff.c_str( )," "); if( strcmp( buff.c_str( ),"nodes")==0){ is_nodes = true; } if( strcmp( buff.c_str( ),"time")==0){ is_triangles = true; timehelpid++; } if( strcmp( buff.c_str( ),"triangles")==0){ is_end = true; } if( strcmp( buff.c_str( ),"end")==0){ if( is_nodes){ is_nodes = false; } if( is_triangles){ is_triangles = false; } if( is_end){ is_end = false; } } if( is_nodes){ string buff3 = buff2; strtok( ( char*)buff3.c_str( )," "); if( strcmp( buff3.c_str( ),"nodes")!=0){ int len = strlen( buff2.c_str( )); int start = 0; int end = 0; char *newbuff = new char[strlen( buff2.c_str( ))+1]; strcpy( newbuff,buff2.c_str( )); for( int i = 0;i<len;i++){ if( newbuff[i] == '\"'){ if( start == 0){ start = i; }else{ end = i; } } } for( int i = start;i<end;i++){ if( newbuff[i] == ' '){ newbuff[i] = '_'; } } char *str_nodeid = strtok( newbuff," "); char *str_nodename = strtok( NULL," "); strcpy( pNodes[atoi( str_nodeid)].nodename,str_nodename); char *str_parent = strtok( NULL," "); pNodes[atoi( str_nodeid)].parent = atoi( str_parent); delete newbuff; } } if( is_triangles){ string buff3 = buff2; strtok( ( char*)buff3.c_str( )," "); if( strcmp( buff3.c_str( ),"time")!=0){ char *str_nodeid = strtok( ( char*)buff2.c_str( )," "); pFrames[timehelpid][atoi( str_nodeid)].nodeid = atoi( str_nodeid); char *str_x = strtok( NULL," "); pFrames[timehelpid][atoi( str_nodeid)].px = ( float)atof( str_x); char *str_y = strtok( NULL," "); pFrames[timehelpid][atoi( str_nodeid)].py = ( float)atof( str_y); char *str_z = strtok( NULL," "); pFrames[timehelpid][atoi( str_nodeid)].pz = ( float)atof( str_z); char *str_rx = strtok( NULL," "); pFrames[timehelpid][atoi( str_nodeid)].rx = ( float)atof( str_rx); char *str_ry = strtok( NULL," "); pFrames[timehelpid][atoi( str_nodeid)].ry = ( float)atof( str_ry); char *str_rz = strtok( NULL," "); pFrames[timehelpid][atoi( str_nodeid)].rz = ( float)atof( str_rz); } } if( is_end){ char t_texhelp[32]; string buff3 = buff2; strtok( ( char*)buff3.c_str( )," "); if( strcmp( buff3.c_str( ),"triangles")!=0){ static int l = 0; if( l == 0){ strcpy( t_texhelp,buff2.c_str( )); }else{ strcpy( pVertices[verthelpid].texturename,t_texhelp); char *str_nodeid = strtok( ( char*)buff2.c_str( )," "); pVertices[verthelpid].nodeid = atoi( str_nodeid); char *str_px = strtok( NULL," "); pVertices[verthelpid].px = ( float)atof( str_px); char *str_py = strtok( NULL," "); pVertices[verthelpid].py = ( float)atof( str_py); char *str_pz = strtok( NULL," "); pVertices[verthelpid].pz = ( float)atof( str_pz); char *str_nx = strtok( NULL," "); pVertices[verthelpid].nx = ( float)atof( str_nx); char *str_ny = strtok( NULL," "); pVertices[verthelpid].ny = ( float)atof( str_ny); char *str_nz = strtok( NULL," "); pVertices[verthelpid].nz = ( float)atof( str_nz); char *str_u = strtok( NULL," "); pVertices[verthelpid].u = ( float)atof( str_u); char *str_v = strtok( NULL," "); pVertices[verthelpid].v = ( float)atof( str_v); verthelpid++; } l++; if( l >= 4){ l = 0; } } } } smd2.close( ); return true; } void SMD::Release( void){ if( pNodes){ delete pNodes; } if( pFrames){ delete pFrames; } if( pVertices){ delete pVertices; } } int SMD::GetNumNodes( void){ return numnodes; } int SMD::GetNumFrames( void){ return numframes; } int SMD::GetNumTimes( void){ return numtimes; } int SMD::GetNumVertices( void){ return numvertices; } SMDNode SMD::GetNode( int IndexNode){ return pNodes[IndexNode]; } SMDFrame SMD::GetFrame( int IndexTime,int IndexFrame){ return pFrames[IndexTime][IndexFrame]; } SMDVertex SMD::GetVertex( int IndexVertex){ return pVertices[IndexVertex]; } int SMD::FindNextNode( int Id){ int ret = -1; for( int i = 0;i<GetNumNodes( );i++){ if( GetNode( i).parent == GetNode( Id).parent){ ret = GetNode( i).parent; break; } } return ret; }
Я же сказал я искал ... этот код по моему мнению считается не рабочим, тк пытался заюзать его но он загружает неверно ... К тому же с ошибками.
MelKiY
> Я тут на днях скитался по интернету и искал загрузчик SMD моделей от Half-Life
> 1, но так и не нашёл...
Я не понимаю, КАК нужно искать, чтобы НЕ НАЙТИ загрузчик SMD моделей от Half-Life.
Ну как??!
Было бы великолепно добавить в класс покадровое обновление модели, т.е. установку определенного кадра либо проигрывание последовательности кадров и все, что нужно для отрисовки. Плюс экспортер из 3DS Max (желательно скриптовый *.ms, чтобы на всех версиях работал). Эти вещи, казалось бы, относительно несложные, но, например, мне не хватает времени и мотивации, чтобы написать полноценный класс такой анимации и приходится довольствоваться морфирующей.
Моласар
вперёд найди мне рабочий SMD загрузчик, кроме этого кала: http://www.gamedev.ru/code/faq/?id=3577
old_proger
я с вами согласен, как раз разбираюсь с этим в данный момент
ну а через час у меня днюха :D
Моласар
Погуглил пару минут, нашел только простенькую поделку на сишарпе, если у тебя получится, накидай сюда ссылок.
Может не в тему, но ASSIMP умеет smd, если что, а его исходники в инете есть.
Это на случай если ехать нужно, а не шашечки:)
Вообще формат элементарный, я сам тоже делал для него загрузчик. За пару дней управился просто анализируя SMD файлы в блокноте.
Вот кстати код из ассимпа, про который писали выше.
https://github.com/assimp/assimp/blob/master/code/SMDLoader.cpp
MelKiY
> кроме этого кала:
Этот кал у меня прекрасно работал после замены пары символов
Aslan ну ей богу вы хотя бы заходите на ссылки которые скидываете, мало того что эта ссылка на ресурс не даёт ничего полезного так и ссылка на исходный код не работает ...
MelKiY
Если нужен загрузчик моделей от Half-Life, разве не логично первым делом сделать поиск по файлам Half-Life SDK?
Обратившись к истокам, так сказать.
Тема в архиве.