2005年03月29日

LW→MAX 2

MAXScriptを一つにまとめて、UVも読めるようにした

 

中間ファイルのフォーマット

頂点数
[X,Y,Z]
・・・
テクスチャ頂点数
[U,V,W]
・・・
三角面数
[v1,v2,v3(頂点のインデックス)],[tv1,tv2,tv3(テクスチャ頂点のインデックス)],マテリアルID,エッジ1,エッジ2,エッジ3
ボーン数
ボーン名,親,長さ,[X,Y,Z],[先端の座標],[アップベクタ]
・・・
ボーンウェイト(ボーン数x頂点数個)
・・・

MAXScript

macroScript ImportMesh category:"HowTo"
(
  vert_array = #()
  face_array = #()
  tv_array = #()
  tf_array = #()
  matid_array = #()
  edge_array = #()
  bone_array = #()
 
  in_name = getOpenFileName()
  if in_name != undefined then
  (
    in_file = openFile in_name
    if in_file != undefined then
    (
      num_verts = readValue in_file
      for v = 1 to num_verts do
      (
        append vert_array (readValue in_file)
      )
   num_tv = readValue in_file
   for v=1 to num_tv do
   (
     append tv_array (readValue in_file)
   )
   
      num_faces = readValue in_file
      for f = 1 to num_faces do
      (
        append face_array (readValue in_file)
  append tf_array (readValue in_file)
        append matid_array (readValue in_file)
        edge1 = readValue in_file
        edge2 = readValue in_file
        edge3 = readValue in_file
        append edge_array #(edge1, edge2, edge3)
      )
   
      new_mesh = mesh vertices:vert_array faces:face_array materialIDs:matid_array tverts:tv_array
   buildTVFaces new_mesh
      for f=1 to num_faces do
      (
        setEdgeVis new_mesh f 1 edge_array[f][1]
        setEdgeVis new_mesh f 2 edge_array[f][2]
        setEdgeVis new_mesh f 3 edge_array[f][3]
     setTVFace new_mesh f tf_array[f]
      )
   
      update new_mesh
      max modify mode
      select new_mesh
      addModifier new_mesh (Skin())
      skin_mod = new_mesh.modifiers[1]
      num_bones = readValue in_file
      for b = 1 to num_bones do
      (
        bone_name = readDelimitedString in_file ","
        bone_parent = readValue in_file
        bone_length = readValue in_file
        bone_pos = readValue in_file
        bone_tip = readValue in_file
        bone_upvec = readValue in_file
        bone = BoneSys.createBone bone_pos bone_tip bone_upvec
        append bone_array bone
        bone.name = bone_name
        bone.width = bone_length * 0.2
        bone.height = bone_length * 0.2
        bone.setBoneEnable true 0
        if 0 < bone_parent then
          bone.parent = bone_array[bone_parent]
        skinops.addbone skin_mod bone 1
      )
  
      max modify mode
      select new_mesh
   skin_mod = new_mesh.modifiers[1]
      if num_bones == skinops.getNumberBones skin_mod then
      (
     for b = 1 to num_bones do
     (
    for v = 1 to num_verts do
    (
      weight = readValue in_file
      skinOps.setVertexWeights skin_mod v b weight
    )--v
        )--b
   )--num_bone
  
      close in_file
    )--OpenFile
  )--GetFileName
)--


LayoutGeneric.cpp

#include "main.h"
#include "LW_CMatrix.h"

#include <vector>
#include <string>

typedef std::vector<LWPntID> PointIDList;
typedef std::vector<LWPolID> PolygonIDList;
typedef std::string String;
typedef std::vector<String> StringList;
typedef std::vector<float> FList;
typedef struct{
  String    name;
  LWFVector  pos, tip, upvec;
  int      parentIndex, selfIndex;
  FList    weights;
  LWItemID  id;
  float    length;
}BoneData;
typedef std::vector<BoneData> BoneList;


static LWPanControlDesc    desc;   // required by macros in lwpanel.h
static LWValue        ival={LWT_INTEGER};
static LWValue        ivecval={LWT_VINT};    // required by macros in lwpanel.h
static LWValue        fval={LWT_FLOAT};
static LWValue        fvecval={LWT_VFLOAT};
static LWValue        sval={LWT_STRING};


int getPntIDFunc(void *scanData, LWPntID pnt);
int getPolyIDFunc(void *scanData, LWPolID pol);
bool getFilename(GlobalFunc *global, char *filename, int maxlen);
DWORD getVIndex(const PointIDList *points, const LWPntID pnt);
int getSurfIndex(const StringList *NameList, const char *name, int numName);
void getBone(const LWItemInfo *iteminfo, const LWBoneInfo *boninfo, LWItemID bone, BoneList *bonlist, int parentIndex);
const char * getUVName(GlobalFunc *global, String &name);

//----------------------------------------------------------------------------------------------------
//  ハンドラーアクティベーション関数
//----------------------------------------------------------------------------------------------------
XCALL_(int) Activate(long version, GlobalFunc *global, LWLayoutGeneric *local, void *serverData)
{
  if( LWLAYOUTGENERIC_VERSION != version )
    return AFUNC_BADVERSION;

  LWInterfaceInfo  *intinfo = (LWInterfaceInfo*)global( LWINTERFACEINFO_GLOBAL, GFUSE_TRANSIENT );
  LWItemInfo    *iteminfo = (LWItemInfo*)global( LWITEMINFO_GLOBAL, GFUSE_TRANSIENT );
  LWMessageFuncs  *msgf = (LWMessageFuncs*)global( LWMESSAGEFUNCS_GLOBAL, GFUSE_TRANSIENT );
  LWObjectInfo  *objinfo = (LWObjectInfo*)global( LWOBJECTINFO_GLOBAL, GFUSE_TRANSIENT );
  LWSurfaceFuncs  *surff = (LWSurfaceFuncs*)global( LWSURFACEFUNCS_GLOBAL, GFUSE_TRANSIENT );
  LWBoneInfo    *boninfo = (LWBoneInfo*)global( LWBONEINFO_GLOBAL, GFUSE_TRANSIENT );
  const char    *error;

  if( !intinfo || !iteminfo || !msgf || !objinfo || !surff || !boninfo )
    return AFUNC_BADGLOBAL;

  LWItemID  obj = *(intinfo->selItems);
  if( LWI_OBJECT != iteminfo->type(obj) ){
    msgf->error("", "");
    return AFUNC_OK;
  }

  LWMeshInfoID  meshinfo = objinfo->meshInfo(obj, 0);
  if( !meshinfo ){
    msgf->error("", "");
    return AFUNC_OK;
  }

  String  UVName;
  error = getUVName(global, UVName);
  if( error ){
    msgf->error(error, "");
  }

//ポイント
  DWORD  numPnts = meshinfo->numPoints(meshinfo);
  PointIDList  pnts;
  meshinfo->scanPoints(meshinfo, getPntIDFunc, &pnts);

//ポリゴン
  DWORD  numPolys = meshinfo->numPolygons(meshinfo);
  PolygonIDList  pols;
  meshinfo->scanPolys(meshinfo, getPolyIDFunc, &pols);
  void *vmap = meshinfo->pntVLookup(meshinfo, LWVMAP_TXUV, UVName.c_str());
  if( !vmap ){
    msgf->error("", "");
    return AFUNC_OK;
  }
  meshinfo->pntVSelect(meshinfo, vmap);
  FList  uv;
  for(DWORD numTriPolys=0, dw=0; dw<numPolys; dw++){
    int nVert = meshinfo->polSize(meshinfo, pols[dw]);
    LWFVector  fvec = { 0.0, 0.0, 0.0 };
    if( 3 == nVert ){
      numTriPolys++;
      for(int i=0; i<nVert; i++){
        if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], i), pols[dw], fvec) ){
          uv.push_back(fvec[0]);
          uv.push_back(fvec[1]);
        }
      }
    }else if( 3 < nVert ){
      numTriPolys += (nVert - 2);
      for(int i=0; i<nVert; i++){
        if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], i), pols[dw], fvec) ){
          uv.push_back(fvec[0]);
          uv.push_back(fvec[1]);
        }
      }
    }
  }

//サーフェイス
  LWSurfaceID  *surfID = surff->byObject(objinfo->filename(obj));
  int  numSurf;
  for( numSurf=0; surfID[numSurf]; numSurf++) ;
  StringList  surfNameList;
  String  tempString;
  for(int i=0; i<numSurf; i++){
    tempString = surff->name(surfID[i]);
    surfNameList.push_back(tempString);
  }

//ボーン
  BoneList  bones;
  for(LWItemID child=iteminfo->firstChild(obj); LWITEM_NULL != child; child=iteminfo->nextChild(obj, child)){
    if( LWI_BONE == iteminfo->type(child) ) getBone(iteminfo, boninfo, child, &bones, -1);
  }
  DWORD  numBones = bones.size();
  for(dw=0; dw<numBones; dw++){
    const char *weightName = boninfo->weightMap(bones[dw].id);
    float  tempF;
    if( weightName ){
      vmap = meshinfo->pntVLookup(meshinfo, LWVMAP_WGHT, weightName);
      if( vmap ){
        meshinfo->pntVSelect(meshinfo, vmap);
        for(int i=0; i<numPnts; i++){
          if( !meshinfo->pntVGet(meshinfo, pnts[i], &tempF) ){
            tempF = 0.0;
          }
          bones[dw].weights.push_back(tempF);
        }
      }else{
        for(i=0; i<numPnts; i++){
          bones[dw].weights.push_back(0.0);
        }
      }
    }else{
      for(int i=0; i<numPnts; i++){
        bones[dw].weights.push_back(0.0);
      }
    }
  }

//ファイルに出力
  char  filename[MAX_PATH];
  if( !getFilename(global, filename, MAX_PATH) ){
    msgf->error("", "");
    return AFUNC_OK;
  }

  FILE  *fp = fopen(filename, "wt");
  if( !fp ){
    msgf->error("", "");
    return AFUNC_OK;
  }

  LWFVector  pos;
  fprintf(fp, "%d\n", numPnts);
  for(dw=0; dw<numPnts; dw++){
    meshinfo->pntBasePos(meshinfo, pnts[dw], pos);
    fprintf(fp, "[%f,%f,%f]\n", pos[0]*39.37, pos[2]*39.37, pos[1]*39.37);
  }

  DWORD numUVPnts = uv.size()*0.5;
  fprintf(fp, "%d\n", numPnts+numUVPnts );
  vmap = meshinfo->pntVLookup(meshinfo, LWVMAP_TXUV, UVName.c_str());
  meshinfo->pntVSelect(meshinfo, vmap);
  for(dw=0; dw<numPnts ; dw++){
    LWFVector fvec;
    if( meshinfo->pntVGet(meshinfo, pnts[dw], fvec) ){
      fprintf(fp, "[%f,%f,0.0]\n", fvec[0], fvec[1]);
    }else{
      fprintf(fp, "[0.0,0.0,0.0]\n");
    }
  }
  for(dw=0 ;dw<(numUVPnts*2); dw+=2){
    fprintf(fp, "[%f,%f,0.0]\n", uv[dw], uv[dw+1]);
  }

  int  vIndex[3];
  int uvwIndex[3];
  DWORD uvwCurrent = numPnts + 1;
  int matIndex;
  const char *edgeIndex[3];
  fprintf(fp, "%d\n", numTriPolys);
  for(dw=0; dw<numPolys; dw++){
    LWFVector  fvec;
    int  nVert = meshinfo->polSize(meshinfo, pols[dw]);
    matIndex = getSurfIndex(&surfNameList, meshinfo->polTag(meshinfo, pols[dw], LWPTAG_SURF), numSurf);
    if( 3 == nVert ){
      vIndex[0] = getVIndex(&pnts, meshinfo->polVertex(meshinfo, pols[dw], 2)) +1;
      vIndex[1] = getVIndex(&pnts, meshinfo->polVertex(meshinfo, pols[dw], 1)) +1;
      vIndex[2] = getVIndex(&pnts, meshinfo->polVertex(meshinfo, pols[dw], 0)) +1;
      if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], 2), pols[dw], fvec) ) uvwIndex[0] = uvwCurrent++; else uvwIndex[0] = vIndex[0];
      if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], 1), pols[dw], fvec) ) uvwIndex[1] = uvwCurrent++; else uvwIndex[1] = vIndex[1];
      if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], 0), pols[dw], fvec) ) uvwIndex[2] = uvwCurrent++; else uvwIndex[2] = vIndex[2];
      edgeIndex[0] = "true"; edgeIndex[1] = "true"; edgeIndex[2] = "true";
      fprintf(fp, "[%d,%d,%d],[%d,%d,%d],%d,%s,%s,%s\n", vIndex[0], vIndex[1], vIndex[2], uvwIndex[0], uvwIndex[1], uvwIndex[2], matIndex, edgeIndex[0], edgeIndex[1], edgeIndex[2]);
    }else if( 3 < nVert ){
      vIndex[0] = getVIndex(&pnts, meshinfo->polVertex(meshinfo, pols[dw], nVert - 1)) +1;
      vIndex[1] = getVIndex(&pnts, meshinfo->polVertex(meshinfo, pols[dw], nVert - 2)) +1;
      vIndex[2] = getVIndex(&pnts, meshinfo->polVertex(meshinfo, pols[dw], nVert - 3)) +1;
      if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], nVert - 1), pols[dw], fvec) ) uvwIndex[0] = uvwCurrent++; else uvwIndex[0] = vIndex[0];
      if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], nVert - 2), pols[dw], fvec) ) uvwIndex[1] = uvwCurrent++; else uvwIndex[1] = vIndex[1];
      if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], nVert - 3), pols[dw], fvec) ) uvwIndex[2] = uvwCurrent++; else uvwIndex[2] = vIndex[2];
      edgeIndex[0] = "true"; edgeIndex[1] = "true"; edgeIndex[2] = "false";
      fprintf(fp, "[%d,%d,%d],[%d,%d,%d],%d,%s,%s,%s\n", vIndex[0], vIndex[1], vIndex[2], uvwIndex[0], uvwIndex[1], uvwIndex[2], matIndex, edgeIndex[0], edgeIndex[1], edgeIndex[2]);
      edgeIndex[0] = "false";
      for(int i=nVert-4; i>=0; i--){
        vIndex[1] = vIndex[2];
        uvwIndex[1] = uvwIndex[2];
        vIndex[2] = getVIndex(&pnts, meshinfo->polVertex(meshinfo, pols[dw], i)) +1;
        if( meshinfo->pntVPGet(meshinfo, meshinfo->polVertex(meshinfo, pols[dw], i), pols[dw], fvec) ) uvwIndex[2] = uvwCurrent++; else uvwIndex[2] = vIndex[2];
        if( 0 == i ) edgeIndex[2] = "true";
        fprintf(fp, "[%d,%d,%d],[%d,%d,%d],%d,%s,%s,%s\n", vIndex[0], vIndex[1], vIndex[2], uvwIndex[0], uvwIndex[1], uvwIndex[2], matIndex, edgeIndex[0], edgeIndex[1], edgeIndex[2]);
      }
    }
  }

  fprintf(fp, "%d\n", numBones);
  for(dw=0; dw<numBones; dw++){
    fprintf(fp, "%s,", bones[dw].name.c_str());
    fprintf(fp, "%d,", bones[dw].parentIndex + 1);
    fprintf(fp, "%f,", bones[dw].length*39.37);
    fprintf(fp, "[%f,%f,%f],", bones[dw].pos[0]*39.37, bones[dw].pos[2]*39.37, bones[dw].pos[1]*39.37);
    fprintf(fp, "[%f,%f,%f],", bones[dw].tip[0]*39.37, bones[dw].tip[2]*39.37, bones[dw].tip[1]*39.37);
    fprintf(fp, "[%f,%f,%f]\n", bones[dw].upvec[0]*39.37, bones[dw].upvec[2]*39.37, bones[dw].upvec[1]*39.37);
  }

  for(dw=0; dw<numBones; dw++){
    for(DWORD i=0; i<numPnts; i++){
      fprintf(fp, "%f\n", bones[dw].weights[i]);
    }
  }

  return AFUNC_OK;
}

 

 

int getPntIDFunc(void *scanData, LWPntID pnt)
{
  PointIDList    *p = (PointIDList*)scanData;
  p->push_back(pnt);
  return 0;
}


int getPolyIDFunc(void *scanData, LWPolID pol)
{
  PolygonIDList  *p = (PolygonIDList*)scanData;
  p->push_back(pol);
  return 0;
}


bool getFilename(GlobalFunc *global, char *filename, int maxlen)
{
  LWFileReqFunc  *filereq = (LWFileReqFunc*)global( LWFILEREQFUNC_GLOBAL, GFUSE_TRANSIENT );
  if( !filereq ) return false;

  static char  node[MAX_PATH] = "*.txt";
  static char path[MAX_PATH] = "";

  int  result = filereq("Save", node, path, filename, maxlen);
  if( result ) return true;
  else return false;
}


DWORD getVIndex(const PointIDList *points, const LWPntID pnt)
{
  for(DWORD dw=0; (*points)[dw] != pnt; dw++) ;

  return dw;
}


int getSurfIndex(const StringList *NameList, const char *name, int numName)
{
  for(int i=0; i<numName; i++){
    if( 0 == strcmp((*NameList)[i].c_str(), name) ) return i+1;
  }
  return 0;
}

LW_CMatrix_4x4 getMatrix(LW_CMatrix_4x4 matrix, const LWItemInfo *iteminfo, const LWBoneInfo *boninfo, LWItemID id)
{
  LW_CMatrix_4x4  temp;
  if( LWITEM_NULL == id || LWI_BONE != iteminfo->type(id) ) return matrix;

  LWDVector  dvec;
  boninfo->restParam(id, LWIP_ROTATION, dvec);
  temp.rotateHPB(dvec[0], dvec[1], dvec[2]);
  boninfo->restParam(id, LWIP_POSITION, dvec);
  temp.translate(dvec[0], dvec[1], dvec[2]);

  return getMatrix(matrix * temp, iteminfo, boninfo, iteminfo->parent(id));
}

void getBone(const LWItemInfo *iteminfo, const LWBoneInfo *boninfo, LWItemID bone, BoneList *bonlist, int parentIndex)
{
  BoneData  bondata;
  bondata.id = bone;
  bondata.name = iteminfo->name(bone);
  bondata.parentIndex = parentIndex;
  bondata.selfIndex = bonlist->size();
  bondata.length = boninfo->restLength(bone);
  bondata.pos[0] = 0.0; bondata.pos[1] = 0.0; bondata.pos[2] = 0.0;
  bondata.tip[0] = 0.0; bondata.tip[1] = 0.0; bondata.tip[2] = bondata.length;
  bondata.upvec[0] = 0.0; bondata.upvec[1] = 1.0; bondata.upvec[2] = 0.0;
  LW_CMatrix_4x4 matrix;
  matrix.init();
  matrix = getMatrix(matrix, iteminfo, boninfo, bone);
  matrix.Transform(bondata.pos);
  matrix.Transform(bondata.tip);
  matrix.Transform(bondata.upvec);

  bonlist->push_back(bondata);

  for(LWItemID child=iteminfo->firstChild(bone); LWITEM_NULL != child; child=iteminfo->nextChild(bone, child)){
    if( LWI_BONE == iteminfo->type(child) ) getBone(iteminfo, boninfo, child, bonlist, bondata.selfIndex);
  }
}


const char * getUVName(GlobalFunc *global, String &name)
{
  LWObjectFuncs  *objfunc = (LWObjectFuncs*)global( LWOBJECTFUNCS_GLOBAL, GFUSE_TRANSIENT );
  LWPanelFuncs  *panel = (LWPanelFuncs*)global(LWPANELFUNCS_GLOBAL, GFUSE_TRANSIENT);
  LWPanelID    pid = NULL;
  LWControl    *ctl;

  if( !objfunc || !panel ) return false;

  int numMaps = objfunc->numVMaps(LWVMAP_TXUV);
  if( 0 == numMaps ){
    return "There is not UVMaps.";
  }else if( 1 == numMaps ){
    name = objfunc->vmapName(LWVMAP_TXUV, 0);
    return NULL;
  }
  const char **items = new const char*[numMaps+1];
  for(int i=0; i<numMaps; i++){
    items[i] = objfunc->vmapName(LWVMAP_TXUV, i);
  }
  items[numMaps] = NULL;

  if( pid = PAN_CREATE(panel, SERVERNAME) ){
    ctl = POPUP_CTL(panel, pid, "Select UVMap", items);
    if( PAN_POST(panel, pid) ){
      GET_INT(ctl, i);
      name = items[i];
    }else{
      return "Canceled";
    }
    PAN_KILL(panel, pid);
  }
  return NULL;
}

posted by toka at 15:05| Comment(0) | TrackBack(0) | LWプラグイン開発 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:


この記事へのトラックバック
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。