Вторник, 16 Апреля 2024, 13:53

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 3 из 3
  • «
  • 1
  • 2
  • 3
Форум игроделов » Ваши проекты » Готовые проекты » Onigeine
Onigeine
WXZRWДата: Понедельник, 21 Сентября 2009, 14:36 | Сообщение # 41
Thousand faces conspiration
Сейчас нет на сайте
Quote (Akyltist)
Понятно, значит ты от Вафли опираешься, тогда тебе нужен Mdl именно для HL копать

Да, только не на mdl а на smd. Mdl это пропиетарный формат, не покатит...

Quote (Akyltist)
Он конечно закодированный но декомпиляция его проста. Вот тебе сорцы по его декомпиляции.

Это для первой халвы, вторую версию mdl он не поддерживает. Надо от HL2 modelviewer. Хотя я попробую без него обойтись, или если что, можно миксовать по своему, поскольку нет необходимости полного соответствия с тем как Valve делает.

Мне smd вообще нужен как промежуточный формат, для конвертации в свой, просто я обратил внимание на QC команды. То есть он вообще не поддерживается в моем двиге.

AkyltistДата: Понедельник, 21 Сентября 2009, 15:18 | Сообщение # 42
заслуженный участник
Сейчас нет на сайте
Для HalfLife2 используют тот-же формат что и для первой (за исключением весов для вершин)

Если тебе нужно SMD получать их MDL и далее с ними работать, то зачем тащить mdl, конверти их на стадии разработки, декомпилер mdl > smd есть по ссылке выше, если нужен то сделаем чтобы со второй халфы декомпилил в smd. Хотя и тот что выше должен подойти для этих целей. А уже с полученным смд работай сам. Если как промежуточный то просто лоди SMD пример ниже и работай как хочешь.

Пример кода по загрузки *.SMD

Code
typedef float vec3f[3];
typedef float vec2f[2];
typedef unsigned short word;
#define Dword unsigned long
typedef Dword vec3l[3];

class Tmesh{
   public:

    Dword mv;  // количество вершин (Vertex)
     vec3f *v;    // сами вершины
     vec2f *t;     // текстурные координаты
     byte *mbi;  // количество костей на вершину
     int **bi;      // индексы костией привязанных к вершине
     float **sbi; // веса костей

    Dword mf;   // количестко треугольников (Faces)
     vec3l *f;     // массив индексов треугольников
     int *ti;        // индекс текстуры треугольника

    byte mb;           // количество костей во всей модели
     vec3f *bv,*ba; // bv-положение кости ba-ориетнация кости
     int *p;              // индекс родителя кости

    word mtx;     // количество текстур
     int *tnl,*txi; // tnl-длинна имени текстуры txi-индекс текстуры в видео памяти (glGenTex(1,&txi[i]))
     char **txn;  // имя текстуры
   ....
};

typedef struct{
   word max_tkf,max_rkf; // количество фреймов поворотов и смещений
   vec3f *rot,*pos;           // поворот и смещение   
   float *Ttime,*Rtime;     // номер фрейма
   void init(){
    max_tkf=max_rkf=0;
    rot=pos=NULL;
    Ttime=Rtime=NULL;
   };
}TMAFrame;

class Tanim{
   public:
    Dword max_b,max_fr; // количество костей и фреймов анимации
    TMAFrame *fr;             // массив фреймов
    void Initfr(){     
     for(int i=0;i<mb;i++){fr[i].init();};
    };
};

bool Load_HL12SMD(char *name,Tmesh *m,Tanim *a){
   // для работы с файлами подключить #include <stdio.h>
   FILE *in=fopen(name,"rb");   
   if(in==NULL){ALERT("HL12SMD::can't load (%s)",name);return 0;};
   char buf[4096];
   char bname[1024];
   int parent;
   Dword mf=0,mv=0,i,j,k;
   byte mb=0;
   float tf;
   int ti;

   //сперва определим количества (вершин костей ...и тд) и выделим память
   while(fgets(buf,4095,in)){

    // считаем кости
    if(strcmp(buf,"nodes")){while(fgets(buf,4095,in)){
     if(strcmp(buf,"end")){
      m->mb=mb;
      m->bv=new vec3f[mb];
      m->ba=new vec3f[mb];
      m->p=new int[mb];
      a->max_b=mb;
      a->fr=new TMAFrame[mb];a->Initfr();      
      break;
     };
     mb++;
    };};   

    // считаем треугольники
    if(strcmp(buf,"triangles")){while(fgets(buf,4095,in)){
     if(strcmp(buf,"end")){
      m->mv=mv;
      m->v=new vec3f[mv];
      m->t=new vec2f[mv];
      m->ti=new int[mv];      
      if(mb>0){
       m->mbi=new byte[mv];
       m->bi=new int*[mv];
       m->sbi=new float*[mv];            
      };
      m->mf=mf;
      m->f=new vec3l[mf];
      break;
     };

     // покачто не нужная информация - пропускаем
     fgets(buf,4095,in);fgets(buf,4095,in);fgets(buf,4095,in);
     mf++;
     mv+=3;
    };};
   };

   // сбрасываем позицию чтения файла на начало
   rewind(in);

   // заполняем массивы
   while(fgets(buf,4095,in)){
      
    //читаем имена и индксы костей (я не сохраняю имена)
    if(strcmp(buf,"nodes")){
     for(i=0;i<mb;i++){
      fgets(buf,4095,in);
      sscanf(buf,"%d \"%[^\"]\" %d",&ti,bname,&parent);
      m->p[i]=parent;
     };
    };

    // читаем сами кости
    if(strcmp(buf,"skeleton")){
     fgets(buf,4095,in);//time 0
     for(i=0;i<mb;i++){fgets(buf,4095,in);
      sscanf(buf,"%d %f %f %f %f %f %f",&ti,&m->bv[i][0],&m->bv[i][1],&m->bv[i][2],
                     &m->ba[i][0],&m->ba[i][1],&m->ba[i][2]);
     };

     // чтение анимации
     //(!)важно(!) анимация уже перемножена с начальным положением костей
     char cmd[10];
     Dword fcnt=0;
     a->max_fr=0;
     bool animFound=false;
     while(fgets(buf,4095,in)){
      sscanf(buf,"%s %d",cmd,&k);
      if(strcmp(cmd,"end")){if(!animFound){a->max_b=0;};break;};
      if(strcmp(cmd,"time")){animFound=true;
       a->max_fr++;
       for(i=0;i<mb;i++){fgets(buf,4095,in);
        a->fr[i].max_tkf++;
        a->fr[i].pos=(vec3f*)realloc(a->fr[i].pos,sizeof(vec3f)*a->fr[i].max_tkf);
        a->fr[i].Ttime=(float*)realloc(a->fr[i].Ttime,sizeof(float)*a->fr[i].max_tkf);
        a->fr[i].max_rkf++;
        a->fr[i].rot=(vec3f*)realloc(a->fr[i].rot,sizeof(vec3f)*a->fr[i].max_rkf);
        a->fr[i].Rtime=(float*)realloc(a->fr[i].Rtime,sizeof(float)*a->fr[i].max_rkf);
        fcnt=a->fr[i].max_tkf-1;
        a->fr[i].Ttime[fcnt]=(float)k;
        a->fr[i].Rtime[fcnt]=(float)k;
        sscanf(buf,"%d %f %f %f %f %f %f",&ti,&a->fr[i].pos[fcnt][0],&a->fr[i].pos[fcnt][1],&a->fr[i].pos[fcnt][2],
                     &a->fr[i].rot[fcnt][0],&a->fr[i].rot[fcnt][1],&a->fr[i].rot[fcnt][2]);
       };
      };
     };
    };   

    //читаем треугольники
    if(strcmp(buf,"triangles")){
     int nb,bi[5];
     Dword cnt=0,index;
     float bw[5];
     vec3f RV;
     vec2f RT;
     for(i=0;i<mf;i++){
       
       // сперва идёт имя текстуры   
       memset(buf,'\0',4095);fgets(buf,4095,in);
       if(buf[0]=='\0'){m->ti[i]=0;}else{
       long num=-1;
       buf[strlen(buf)-1]='\0';buf[strlen(buf)-1]='\0';//'\n\t'
       for(j=0;j<m->mtx;j++){if(!strcmp(m->txn[j],buf))continue;num=j;break;};
       if(num==-1){m->ti[i]=m->mtx;
        m->mtx++;
        m->tnl=(int*)realloc(m->tnl,sizeof(int)*m->mtx);m->tnl[m->mtx-1]=strlen(buf)+1;
        m->txi=(int*)realloc(m->txi,sizeof(int)*m->mtx);m->txi[m->mtx-1]=num;
        m->txn=(char**)realloc(m->txn,sizeof(char*)*m->mtx);
         m->txn[m->mtx-1]=new char[m->tnl[m->mtx-1]];
          memcpy(m->txn[m->mtx-1],buf,sizeof(char)*m->tnl[m->mtx-1]);
          m->txn[m->mtx-1][m->tnl[m->mtx-1]]='\0';
       }else{m->ti[i]=num;};
      };

      //после имени текстуры следуют 3 вершины (со всеми свойствами)    
      for(j=0;j<3;j++){fgets(buf,4095,in);
       nb=0;

       // читаем
       // %d - индекс кости (если привязано к вершине всего одна кость)
       // %f %f %f - вершина
       // %f %f %f - нормаль (я не сохраняю)
       // %f %f - текстурные координаты
       // %d - количество привязанных костей   
       // %d %f ....... - индекс кости и её вес (weight)
       // вроде больше чем 5 костей на вершину не встречал
       int numRead=sscanf(buf,"%d %f %f %f %f %f %f %f %f %d %d %f %d %f %d %f %d %f",&ti,
        &RV[0],&RV[1],&RV[2],&tf,&tf,&tf,&RT[0],&RT[1],
        &nb,&bi[0],&bw[0],&bi[1],&bw[1],&bi[2],&bw[2],&bi[3],&bw[3],&bi[4],&bw[4]);
        RT[1]=RT[1]+1.0f;
        if(nb==0){nb=1;bi[0]=ti;bw[0]=1.0;};

       // проверка: дублирование вершины (если да то запоминаем индекс)
       //-------------find face index
       index=cnt;
       for(k=0;k<cnt;k++){
        if(m->v[k][0]==RV[0] && m->v[k][1]==RV[1] && m->v[k][2]==RV[2] && m->t[k][0]==RT[0] && m->t[k][1]==RT[1]){
         index=k;break;
        };
       };
       m->f[i][j]=index;
       if(index==cnt){
        COPY(m->v[index],RV);
        COPY2(m->t[index],RT);
        //-------------------bones
        if(mb>0){
         m->mbi[index]=nb;
         m->bi[index]=new int[nb];
         m->sbi[index]=new float[nb];
         for(k=0;k<(Dword)nb;k++){
          m->bi[index][k]=bi[k];
          m->sbi[index][k]=bw[k];
         };
        };   
        //-----------------end bones
        cnt++;
       };
       //------------end find index
      };
      // меняем порядок обхода вершин
      k=m->f[i][0];m->f[i][0]=m->f[i][2];m->f[i][2]=k;
     };
     m->mv=cnt;
    };
   };
   fclose(in);
   return true;
};

// ниже функции используемые в загрузке
void ALERT(const char *messag, ...){
   char text[1024];
   va_list ap;
   va_start(ap,messag);
   vsprintf(text,messag,ap);
   va_end(ap);
   MessageBox(NULL,text,"ALERT",MB_SETFOREGROUND);
};   

#define COPY(dest,v1)dest[0]=v1[0];dest[1]=v1[1];dest[2]=v1[2];
#define COPY2(v1,v2)v1[0]=v2[0];v1[1]=v2[1];

По секрету, я свой код стащил из огры.))
WXZRWДата: Понедельник, 21 Сентября 2009, 15:34 | Сообщение # 43
Thousand faces conspiration
Сейчас нет на сайте
Quote (Akyltist)
Для HalfLife2 используют тот-же формат что и для первой (за исключением весов для вершин)

SMD такой же, но имхо там во второй халве переделали смешивание. То есть, там аккумулируются позы, в первой халве этого не было, насколько я знаю. Исходник modelviewer'a от второй халвы более сложный чем для первой.

Quote (Akyltist)
Если тебе нужно SMD получать их MDL и далее с ними работать, то зачем тащить mdl, конверти их на стадии разработки, декомпилер mdl > smd есть по ссылке выше, если нужен то сделаем чтобы со второй халфы декомпилил в smd. Хотя и тот что выше должен подойти для этих целей. А уже с полученным смд работай сам. Если как промежуточный то просто лоди SMD пример ниже и работай как хочешь.

У меня smd напрямую конвертится в свой формат, сам smd выдергиваю из mdl. То есть анимация в двиге уже есть, с блендингом, только вот небольшой вопрос насчет poseparameter остался :)

Quote (Akyltist)
Пример кода по загрузки *.SMD

ОК, спасибо, гляну.

AkyltistДата: Понедельник, 21 Сентября 2009, 15:42 | Сообщение # 44
заслуженный участник
Сейчас нет на сайте
poseparameter самого объекта или костей? скинь код где ты с ним работаешь, так быстрее дойдет что тебе точно нужно.
AkyltistДата: Вторник, 17 Ноября 2009, 16:35 | Сообщение # 45
заслуженный участник
Сейчас нет на сайте
Проект завершен 17.11.2009


Благодарности:
1. Спасибо всем с джабер канала, думаю еще месяца 2 и там будет сидеть вся основная тусовка, весь GCUP андеграунд. 2. Спасибо Vinchensoo, не один час мы с ним убили над обсуждением всего этого, спасибо что терпел мои заморочки.
3. Спасибо сестренке Настене, без тебя солнце ничего бы вообще не было, ты самое дорогое что у меня есть в жизни, давай поправляйся.
4. Спасибо администрации портала, за то что терпели мои капризы.
5. Спасибо моему чайнику и глобальной сети интернет, без Вас я бы тоже не справился.
6. Огромное спасибо Элизабет, моей малышке машинке. Именно она рендерила и исполняла эти непонятные наборы символов.

Форум игроделов » Ваши проекты » Готовые проекты » Onigeine
  • Страница 3 из 3
  • «
  • 1
  • 2
  • 3
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг