ПрограммированиеФорумГрафика

Half-Life 1 SMD загрузчик

#0
21:03, 6 дек 2014

Всем привет. Я тут на днях скитался по интернету и искал загрузчик 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;
}
#1
21:05, 6 дек 2014

MelKiY
http://www.gamedev.ru/code/faq/?id=3577

#2
21:17, 6 дек 2014

Я же сказал я искал ... этот код по моему мнению считается не рабочим, тк пытался заюзать его но он загружает неверно ... К тому же с ошибками.

#3
22:00, 6 дек 2014

MelKiY
> Я тут на днях скитался по интернету и искал загрузчик SMD моделей от Half-Life
> 1, но так и не нашёл...
Я не понимаю, КАК нужно искать, чтобы НЕ НАЙТИ загрузчик SMD моделей от Half-Life.
Ну как??!

#4
22:28, 6 дек 2014

Было бы великолепно добавить в класс покадровое обновление модели, т.е. установку определенного кадра либо проигрывание последовательности кадров и все, что нужно для отрисовки. Плюс экспортер из 3DS Max (желательно скриптовый *.ms, чтобы на всех версиях работал). Эти вещи, казалось бы, относительно несложные, но, например, мне не хватает времени и мотивации, чтобы написать полноценный класс такой анимации и приходится довольствоваться морфирующей.

#5
23:01, 6 дек 2014

Моласар
вперёд найди мне рабочий SMD загрузчик, кроме этого кала: http://www.gamedev.ru/code/faq/?id=3577

#6
23:04, 6 дек 2014

old_proger
я с вами согласен, как раз разбираюсь с этим в данный момент
ну а через час у меня днюха :D

#7
1:37, 7 дек 2014

Моласар
Погуглил пару минут, нашел только простенькую поделку на сишарпе, если у тебя получится, накидай сюда ссылок.

#8
1:44, 7 дек 2014

Может не в тему, но ASSIMP умеет smd, если что, а его исходники в инете есть.
Это на случай если ехать нужно, а не шашечки:)

#9
13:48, 7 дек 2014

Вообще формат элементарный, я сам тоже делал для него загрузчик. За пару дней управился просто анализируя SMD файлы в блокноте.

Вот кстати код из ассимпа, про который писали выше.
https://github.com/assimp/assimp/blob/master/code/SMDLoader.cpp

#10
13:59, 7 дек 2014

MelKiY
> кроме этого кала:
Этот кал у меня прекрасно работал после замены пары символов

#11
17:54, 8 дек 2014

Aslan ну ей богу вы хотя бы заходите на ссылки которые скидываете, мало того что эта ссылка на ресурс не даёт ничего полезного так и ссылка на исходный код не работает ...

#12
23:17, 8 дек 2014

MelKiY
Если нужен загрузчик моделей от Half-Life, разве не логично первым делом сделать поиск по файлам Half-Life SDK?
Обратившись к истокам, так сказать.

ПрограммированиеФорумГрафика

Тема в архиве.