1. Пользоваться форумом на планшетах и телефонах стало удобнее благодаря Tapatalk

Geometry Cache. Импорт кэша из Max'a

Тема в разделе "Maya", создана пользователем Konstantin Antipov, 7 май 2009.

Модераторы: Dark™, Skif
  1. Konstantin Antipov

    Konstantin Antipov Пользователь сайта

    С нами с:
    24.02.2009
    Сообщения:
    29
    Симпатии:
    0
    Баллы:
    2
    Добрый день!
    Посчитал реактором ткань в максе (9), сохранил Point Cache и OBJ самой ткани.
    Открываю майку(2008 complete), импортнул OBJ, далее говорю Geometry Cache/Import Cache но ничего не выходит, майка ругается: // Error: Selected file has 0 channels and 1 objects are selected. //

    Что делать? Как можно еще перенести анимацию?
    nCloth не могу юзать.
     
  2. alex_alv

    alex_alv Активный участник

    С нами с:
    23.04.2008
    Сообщения:
    150
    Симпатии:
    0
    Баллы:
    14
    Из макса не импортировал, но сталкивался с проблемами при импорте из Real Flow и из позера. Проблемы решил, написав свою утилиту, которая конвертит некоторые форматы в MA-файл + Geometry Cache. Если проблему решить никто не поможет, пришлите мне на alex_alv@mail.ru Point Cache.
     
  3. Konstantin Antipov

    Konstantin Antipov Пользователь сайта

    С нами с:
    24.02.2009
    Сообщения:
    29
    Симпатии:
    0
    Баллы:
    2
    Все работает на ура! Спасибо alex_alv!
     
  4. alex_alv

    alex_alv Активный участник

    С нами с:
    23.04.2008
    Сообщения:
    150
    Симпатии:
    0
    Баллы:
    14
    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>


    BOOL AskUserFileName(WCHAR * caption,WCHAR * Filter,WCHAR * OutFileName,DWORD fnsize,WCHAR * lpstrDefExt, BOOL Open=TRUE, WCHAR *FileNameWithoutExt=NULL)
    {
    OPENFILENAME ofn;
    BOOL res;
    WORD i;

    ofn.lStructSize=sizeof(ofn);
    ofn.hwndOwner=NULL;
    ofn.lpstrFilter=Filter;
    ofn.lpstrCustomFilter=NULL;
    ofn.nFilterIndex=0;
    ofn.lpstrFile=OutFileName;
    ofn.nMaxFile=fnsize;
    ofn.lpstrFileTitle=NULL;
    ofn.lpstrInitialDir=NULL;
    ofn.lpstrTitle=caption;
    ofn.FlagsEx=0;
    ofn.lpstrDefExt=lpstrDefExt;
    if(Open)
    {
    ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_EXPLORER;
    res=GetOpenFileName(&ofn);
    }else
    {
    ofn.Flags=OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_EXPLORER;
    res=GetSaveFileName(&ofn);
    }
    if((res)&&(FileNameWithoutExt))
    {
    if(ofn.nFileExtension==0)ofn.nFileExtension=0xFFFF;
    for(i=0;i<ofn.nFileExtension;i++)
    {
    FileNameWithoutExt=OutFileName;
    if(OutFileName==0)
    {
    if(i)
    if(FileNameWithoutExt[i-1]==L'.')FileNameWithoutExt[i-1]=0;
    return res;
    }
    }
    FileNameWithoutExt=0;
    if(i)
    if(FileNameWithoutExt[i-1]==L'.')FileNameWithoutExt[i-1]=0;
    }
    return res;
    }

    WCHAR SourceFileName[2000]=L"",OBJFileName[2000]=L"";
    DWORD PC2Header[8],ExtPos;
    float * verts;
    BYTE rdbuffer[2000];

    HANDLE CreateOBJFile(int FrameNumber)
    {
    WCHAR gcn[2000];

    swprintf_s(gcn,2000,L"%s_%u%s",OBJFileName,FrameNumber,SourceFileName+ExtPos);//-StartFrame+1);
    wprintf(L"Creating file %s.\n",gcn);
    return CreateFile ( gcn,
    GENERIC_WRITE,
    FILE_SHARE_READ,
    NULL,
    CREATE_ALWAYS,
    0,
    NULL);
    }

    BOOL ReadFileString(HANDLE hFile,BYTE * buf,DWORD bufsize)
    {
    DWORD i,wrb;
    BYTE b;
    BOOL WasRead,n;

    if(bufsize==0)return FALSE;
    WasRead=FALSE;
    i=0;
    while(1)
    {
    ReadFile(hFile,&b,1,&wrb,NULL);
    if(wrb)WasRead=TRUE;
    if((wrb!=1)||(b==0xA)||(b==0xD))
    {
    if(i>=bufsize) i=bufsize-1;
    buf=0;
    if(WasRead)return TRUE;
    return FALSE;
    }
    if(b==9)b=' ';
    if(i<bufsize)
    {
    if(b==' ')
    if(i==0)n=FALSE;
    else if(buf[i-1]==' ') n=FALSE;
    else n=TRUE;
    else n=TRUE;
    if(n)
    {
    buf=b;
    i++;
    }
    }
    }
    }

    void main()
    {
    HANDLE objFile,pc2file,outfile;
    DWORD wrb,frame,vsize,vn;

    if(!AskUserFileName(L"Open obj-file.",L"OBJ-files\0*.obj\0All files\0*.*\0",SourceFileName,2000,L"OBJ",TRUE))return;
    objFile=CreateFile ( SourceFileName,
    GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    0,
    NULL);
    if(objFile==INVALID_HANDLE_VALUE)
    {
    wprintf(L"Error opening file.\n");
    _getch();
    return;
    }
    SourceFileName[0]=0;
    if(!AskUserFileName(L"Open PC2-file.",L"PS2-files\0*.pc2\0All files\0*.*\0",SourceFileName,2000,L"PC2",TRUE))
    {
    CloseHandle(objFile);
    return;
    }
    pc2file=CreateFile ( SourceFileName,
    GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    0,
    NULL);
    if(pc2file==INVALID_HANDLE_VALUE)
    {
    CloseHandle(objFile);
    wprintf(L"Error opening file.\n");
    _getch();
    return;
    }
    ReadFile(pc2file,PC2Header,32,&wrb,NULL);
    if(wrb!=32)
    {
    CloseHandle(objFile);
    CloseHandle(pc2file);
    wprintf(L"Error reading PC2 header.\n");
    _getch();
    return;
    }
    if((PC2Header[0]!=0x4e494f50)||(PC2Header[1]!=0x43414354)||(PC2Header[2]!=0x00324548)||(PC2Header[4]==0)||(PC2Header[7]==0))
    {
    CloseHandle(objFile);
    CloseHandle(pc2file);
    wprintf(L"Incorrect PC2 header format.\n");
    _getch();
    return;
    }
    wprintf(L"%i verticies and %i frames in the PC2 file.\n",PC2Header[4],PC2Header[7]);
    SourceFileName[0]=0;
    vsize=sizeof(float)*PC2Header[4]*3;
    verts=(float*)HeapAlloc(GetProcessHeap(),0,vsize);
    if(verts==NULL)
    {
    CloseHandle(objFile);
    CloseHandle(pc2file);
    wprintf(L"Error allocating memory.\n");
    _getch();
    return;
    }
    if(!AskUserFileName(L"Create OBJ sequence",L"OBJ-files\0*.obj\0All files\0*.*\0",SourceFileName,2000,L"obj",FALSE,OBJFileName))
    {
    HeapFree(GetProcessHeap(),0,verts);
    CloseHandle(objFile);
    CloseHandle(pc2file);
    return;
    }
    ExtPos=wcsnlen(OBJFileName,2000);
    for(frame=1;frame<=PC2Header[7];frame++)
    {
    outfile=CreateOBJFile(frame);
    if(outfile==INVALID_HANDLE_VALUE)
    {
    HeapFree(GetProcessHeap(),0,verts);
    CloseHandle(objFile);
    CloseHandle(pc2file);
    wprintf(L"Error creating file.\n");
    _getch();
    return;
    }
    SetFilePointer(objFile,0,NULL,FILE_BEGIN);
    vn=0;
    ReadFile(pc2file,verts,vsize,&wrb,NULL);
    if(wrb!=vsize)
    {
    HeapFree(GetProcessHeap(),0,verts);
    CloseHandle(objFile);
    CloseHandle(pc2file);
    wprintf(L"Error reading PC2 file.\n");
    _getch();
    return;
    }
    while(ReadFileString(objFile,rdbuffer,2000))
    {
    if((rdbuffer[0]=='v')&&(rdbuffer[1]==' ')&&(vn<PC2Header[4]))
    {
    sprintf_s((char*)rdbuffer,2000,"v %f %f %f",verts[vn*3],verts[vn*3+2],verts[vn*3+1]);
    vn++;
    }
    WriteFile(outfile,rdbuffer,strnlen((char*)rdbuffer,2000),&wrb,NULL);
    rdbuffer[0]='\n';
    WriteFile(outfile,rdbuffer,1,&wrb,NULL);
    }

    CloseHandle(outfile);
    }
    HeapFree(GetProcessHeap(),0,verts);
    CloseHandle(objFile);
    CloseHandle(pc2file);
    }
     
  5. alex_alv

    alex_alv Активный участник

    С нами с:
    23.04.2008
    Сообщения:
    150
    Симпатии:
    0
    Баллы:
    14
    Это - исходник программы, которая конвертит OBJ и PointCache2 в сиквенцию OBJ
    Консольное приложение под Windows.
    Я компилировал в Visual Studio 2008.
    Думаю, можно компилировать в другом компиляторе, главное, чтобы тип float имел размер 4 байта.

    Конвертацию сиквенции OBJ в MA + Geometry Cache я делал раньше.
     
  6. alex_alv

    alex_alv Активный участник

    С нами с:
    23.04.2008
    Сообщения:
    150
    Симпатии:
    0
    Баллы:
    14
    Компилятор должен использовать UNICODE по умолчанию.
     
  7. alex_alv

    alex_alv Активный участник

    С нами с:
    23.04.2008
    Сообщения:
    150
    Симпатии:
    0
    Баллы:
    14
    Небольшая ошибка, связанная с тем, что в Max похоже ось Y - это майская ось Z со знаком минус. Я в программе взял ее со знаком плюс.
    Для исправления ошибки надо либо скейл объекта по Y поставить отрицательным, либо в программе строку

    sprintf_s((char*)rdbuffer,2000,"v %f %f %f",verts[vn*3],verts[vn*3+2],verts[vn*3+1]);

    заменить на строку

    sprintf_s((char*)rdbuffer,2000,"v %f %f %f",verts[vn*3],verts[vn*3+2],-verts[vn*3+1]);

    На счет формата PC2 на сколько я разобрался:
    первые 32 байта - заголовок.
    В нем первые 12 байт - строка POINTCACHE2 с нулевым символом на конце.
    По смещению +0x10 - целое беззнаковое 32-битное число, определяющее число вершин в каждом кадре кеша.
    По смещению +0x1C - целое беззнаковое 32-битное число, определяющее число кадров в кеше.
    Остальные поля - не знаю.

    После заголовка следуют кадры один за другим подряд. Каждый кадр занимает vn*12 байт, где vn - число вершин (поле +0x10 заголовка)
    Каждый кадр содержит координаты всех вершин. Каждая вершина - 12 байт, состоит из трех float-ов (по 4 байта каждый = по 32 бита).
    Первое число - X-координата (+X для Maya)
    Второе - Y-координата (-Z для Maya)
    Третье - Z-координата (+Y для Maya)
     
Модераторы: Dark™, Skif

Поделиться этой страницей