@warnings @version 2.3 @script modeler @name md5meshImport // Dec 30 2006 // md5mesh import to modeller // clinton Reese // // first goal point cloud single object // point cloud looking good // note: lscript non zero based arrays can throw off logic // second polygons on points // got polygons // third multi mesh layers // we have layers // note: editbegin and editend on polygons has high overhead // do not use on each polygon // fourth bone polygons and/or weightmaps // fourth fake bones // done // fifth weightmaps // sixth uv map // basically done // seventh bones for layout by writting to rig file // have skelegon via convert skelegon but md5 is joints and lw is bones // have to rename skelegons by hand, can use surface name as guide // // PROBLEMS: // No direct way to create bones - work around maybe create rig file // or convert skelegons command // Lightwave is bones, md5mesh is joints // main { // open file myFilename = "file"; dialog = 1; // Open reqbegin("MD5 mesh Loader"); reqsize(251,122); c1 = ctlfilename("Filename",myFilename,,dialog); ctlposition(c1,0,0); return if !reqpost(); myFilename = getvalue(c1); reqend(); thefile = File(myFilename,"r"); // valid file msg = thefile.read(); if(msg != "MD5Version 10") error("not valid md5 ver 10 file"); // initialize variables curmesh = 0; //mesh index procJoints = false; // create a uv map editbegin(); myUVmapObj = VMap(VMTEXTURE,"doomUV",2); if(myUVmapObj == nil) error("no uv created."); editend(); // parse the file while(!thefile.eof()) { msg = thefile.read(); msgtag = parse(" ",msg); if(msgtag[1]=="numJoints") numJoints = msgtag[2];//num of joints if(msgtag[1]=="numMeshes") numMeshes = msgtag[2];//num of meshes // in joint process mode? if(procJoints) { msgtagSub = parse("\t",msgtag[1]);//tab seperates name from rest of data mtSize = msgtagSub[1].size() - 2;//size of joint name minus quotes jointName = strsub(msgtagSub[1],2,mtSize); boneName[curJoint]=jointName; parentIndex[curJoint] = number(msgtagSub[2]) + 1;//add 1 because starts at 0 and lscript index start at 1 //read joint xyz jx[curJoint]=number(msgtag[3]); jy[curJoint]=number(msgtag[4]); jz[curJoint]=number(msgtag[5]); //read joint quaternion xq[curJoint]=number(msgtag[8]); yq[curJoint]=number(msgtag[9]); zq[curJoint]=number(msgtag[10]); //calculate quat w term wq[curJoint]=1.0 - xq[curJoint]*xq[curJoint] - yq[curJoint]*yq[curJoint] - zq[curJoint]*zq[curJoint]; if(wq[curJoint]<0.0) wq[curJoint]=0.0; else wq[curJoint]= sqrt(wq[curJoint]); //fake bones - 2 point poly from curjoint to parentjoint //final joint of all will be missing, md5 is joints not bones //look is correct, but function will be wrong if(curJoint != 1) { // start and end of bone editbegin(); theIndx = parentIndex[curJoint]; bonePoint[1] = addpoint(jx[theIndx], jy[theIndx], jz[theIndx]); bonePoint[2] = addpoint(jx[curJoint], jy[curJoint], jz[curJoint]); editend(); // 2 point poly represent bone editbegin(); addpolygon(bonePoint, jointName); editend(); } curJoint++; if(curJoint>numJoints) { procJoints=false; //merge 2 point poly vertices for convert skelegon mergepoints(); } } //go into joint processing mode next line will be joint data if(msgtag[1]=="joints") { procJoints=true; curJoint=1; emptyLyr = lyrempty();//get list of empty layers lyrsetfg(emptyLyr[1]);//switch to first available layer setlayername("fakeBones"); } if(msgtag[1]=="mesh") { curmesh++; emptyLyr = lyrempty();//get list of empty layers lyrsetfg(emptyLyr[1]);//switch to first available layer } if((msgtag[1]=="\t//") && (msgtag[2]=="meshes:")) { meshName[curmesh]=msgtag[3]; //info(meshName[curmesh]); setlayername(meshName[curmesh]); } if(msgtag[1]=="\tnumverts") numverts = msgtag[2];//num of uv/weight in current mesh //uv + weight info if(msgtag[1]=="\tvert") { curvert = integer(msgtag[2])+1;//uvwvert index + 1 myU[curvert]= number(msgtag[4]); myV[curvert]= number(msgtag[5]); firstWeight[curvert] = integer(msgtag[7])+1;//list of first weights numVWeights[curvert] = integer(msgtag[8]);//number of weights on uv"w" vert } if(msgtag[1]=="\tnumtris") numtris = msgtag[2];//num triangles current mesh //triangle info if(msgtag[1]=="\ttri") { curtri = integer(msgtag[2]) + 1;//triangle index trifaceI[curtri] = integer(msgtag[3]) + 1;//note: may need to reverse for normal dir trifaceJ[curtri] = integer(msgtag[4]) + 1; trifaceK[curtri] = integer(msgtag[5]) + 1; } if(msgtag[1]=="\tnumweights") { numweights = msgtag[2];//number of vertex weights //info(numweights); } //weight info and polygon build if(msgtag[1]=="\tweight") { curweight = integer(msgtag[2]) + 1;//weight index wtJoint[curweight] = integer(msgtag[3]) + 1;//joint associated with this weight weight[curweight] = number(msgtag[4]);//weight value which add to 1.0 for a vertex //XYZ rel joint pos and rot(xyz value in joint local coord system wtX[curweight] = number(msgtag[6]); wtY[curweight] = number(msgtag[7]); wtZ[curweight] = number(msgtag[8]); //if last weight then create polygons if(curweight==numweights) { //info("build point cloud for mesh " + curmesh); editbegin(); for(vt=1;vt<=numverts;vt++) { posX=0.0; posY=0.0; posZ=0.0; wtCnt = numVWeights[vt];//get num weights for current vertex fw = firstWeight[vt];//first weight index for(wt=0;wt