// Doom3 md5mesh import // nov 2005 // clinton reese // joint position is good // no way to parent in script // next do mesh // mesh more involved than I thought // test mesh with cubes first, uses quat rotation to position points relative to the joints // // nov 19 - file data is all being read properly // next get actual point positions and create a box at each vertex(or every other or third or fourth...) // // NOTE: need parseInt(), parseFloat() in some cases to make sure saved as a number // any time you add 2 things they both must be numbers or they add as strings // // mesh successful // but how handle multiple meshes - test has 4 meshes // would also like to import shaders incl normal map // PLAN: // get textures for test model // do uv assignment // try use normal map with color map etc // multiple mesh creation on the fly or select single mesh to load via list box // problem: invisible in player unless copy, then can see copy in player // // multi-mesh problem solved, objects created outside via node create and // copy mesh, material and transform nodes from within owner of this script // use registered mesh attribute so dont need copy and hookup shape node // meshes still not vivible in player without copy or modeller mesh edit // uv harder than expected - little info available // got info but looks like uv stuff is broken // do bones as group object next // // Execute // Called to execute the command function Execute(params) { MyFileName = params.conValue('MyFileName'); // TODO: put your action code here System.Trace("start of import"); var forReading = 1, forWriting = 2, forAppending = 8; rline = new Array(); fs = new ActiveXObject("Scripting.FileSystemObject"); f = fs.GetFile(MyFileName); connToFile = f.OpenAsTextStream( forReading, 0); var count = 0; var myScale = 0.1; while( !connToFile.AtEndOfStream ) { rline[count] = connToFile.ReadLine(); count++; } connToFile.Close(); // finished reading file var msg = ""; var jointCnt = -1; var vertCnt = -1; var numtris = -1; var curmesh = -1; jointMesh = new Array(); firstWeight = new Array(); weightElem = new Array(); //number of weights assigned to vertex triface = new Array(); UVTri = new Array();//uv triangles like triface but with uv instead of vertices meshes = new Array(); meshName = new Array(); // joint position arrays jx = new Array(); jy = new Array(); jz = new Array(); // quaternion arrays for joints xq = new Array(); yq = new Array(); zq = new Array(); wq = new Array(); // weight arrays wtJoint = new Array();//joint index weight = new Array(); //weight value(add to 1 for single vertex) wtX = new Array(); // XYZ relative to joint position and orientation wtY = new Array(); wtZ = new Array() scene = Space.CurrentScene(); for(i = 0; i < rline.length; i++) { msg = rline[i]; // scoop one line from msg array. msgtag = msg.split(" "); if (msgtag[0] == "numJoints") { var numJoints = msgtag[1]; System.Trace("numJoints = " + numJoints); } if (msgtag[0] == "numMeshes") { var numMeshes = msgtag[1]; System.Trace("numMeshes = " + numMeshes); } if (msgtag[0] == "mesh") { curmesh = curmesh + 1; } if (msgtag[0] == "\t//") { if (msgtag[1] == "meshes:") { meshName[curmesh] = msgtag[2]; System.Trace("mesh name is " + meshName[curmesh]); scene = Space.CurrentScene(); encapsO = Node.Create('Kernel Package/Object', scene);//create empty node in scene encaps = Node.Rename(encapsO, meshName[curmesh]); //Node.Copy(name, encaps); owner = System.ThisOwner(); //System.Trace(owner); Node.Copy(owner + "/doomShape", encaps);//copy blank mesh to new node Node.ExportConnector(encaps + "/doomShape","Mesh","",1,1); Node.Copy(owner + "/doomTransform", encaps);//copy transform to new node Node.Rename(encaps + "/doomTransform", "Transform"); Node.ExportConnector(encaps + "/Transform","Matrix","",1,1); Node.ExportConnector(encaps + "/Transform","WldMatrix","",1,1); Node.ExportConnector(encaps + "/Transform","ObjMatrix","",1,1); Node.ExportConnector(encaps + "/Transform","OwnerMatrix","",1,1); Node.Copy(owner + "/doomBlankDXMaterial", encaps);//copy material to new node Node.ExportConnector(encaps + "/doomBlankDXMaterial","Material","",1,1); //TODO export connectors - hopefully can be done //following copied from command stack shows it will be easy //Node.ExportConnector("/Project/Space 3D/fatmesh/doomBlankDXMaterial", "Material", "", 1, 1) } } if (msgtag[0] == "\tnumverts") { var numverts = msgtag[1]; vertCnt = 0; System.Trace("numverts = " + numverts); dT = System.CreateDO("Space 3D Package/UV Coordinate Stream Data"); dT.SetNumUVCoords(numverts); //dT.BeginWrite(); } if (msgtag[0] == "\tvert") { //read uv and index vertCnt = msgtag[1]; dT.u(vertCnt) = msgtag[3]; dT.v(vertCnt) = msgtag[4]; firstWeight[vertCnt] = parseInt(msgtag[6]);// index of first weight for vertex weightElem[vertCnt] = msgtag[7]; // number of weights assigned to vertex if (vertCnt < 2) System.Trace("firstWeight=" + firstWeight[vertCnt] + " count=" + weightElem[vertCnt]); if (vertCnt == numverts-1) { vertCnt = -1; //dT.EndWrite(); } } if (msgtag[0] == "\tnumtris") { numtris = msgtag[1]; triCnt = 0; // define faces triface[curmesh] = System.CreateDO("Space 3D Package/Triangle Vertices Stream Data"); //trivert = System.CreateDO("Space 3D Package/Triangle Vertices Stream Data"); //testUVT = System.CreateDO("Space 3D Package/UV Triangle Stream Data"); //testUVT.SetNumUVTripleIndices(9); //testUVT.i = 0; // testdUV = System.CreateDO("Space 3D Package/UV Coordinate Stream Data"); UVTri[curmesh] = System.CreateDO("Space 3D Package/UV Triangle Stream Data"); UVTri[curmesh].SetNumUVTripleIndices(numtris); //testdUVTr //testM = System.CreateDO("Space 3D Package/Mesh Data"); //test triface[curmesh].SetNumTripleIndices(numtris); triface[curmesh].BeginWrite(); System.Trace("num triangles = " + numtris); } if (msgtag[0] == "\ttri") { triCnt = msgtag[1]; triface[curmesh].i(triCnt) = msgtag[4];//reverse order so face normal is good triface[curmesh].j(triCnt) = msgtag[3]; triface[curmesh].k(triCnt) = msgtag[2]; UVTri[curmesh].i(triCnt) = msgtag[4]; UVTri[curmesh].j(triCnt) = msgtag[3]; UVTri[curmesh].k(triCnt) = msgtag[2]; if (triCnt < 2) System.Trace("face ijk= " + triface[curmesh].i(triCnt) + ", " + triface[curmesh].j(triCnt) + ", " + triface[curmesh].k(triCnt)); if ( triCnt == numtris-1) { triCnt = -1; triface[curmesh].EndWrite(); } } // TODO // use weights to get xyz coord - read in all weights then use firstweight to build vertex stream // later figure out uv coord // much later do skeleton if possible if (msgtag[0] == "\tnumweights") { numweights = msgtag[1]; weightCnt = 0; System.Trace("num weights = " + numweights); } if (msgtag[0] == "\tweight") { weightCnt = msgtag[1]; wtJoint[weightCnt] = msgtag[2]; weight[weightCnt] = msgtag[3]; wtX[weightCnt] = msgtag[5]; wtY[weightCnt] = msgtag[6]; wtZ[weightCnt] = msgtag[7]; if (weightCnt < 2) { System.Trace("index,joint,weight=" + weightCnt + ", "+ wtJoint[weightCnt] + ", " + weight[weightCnt]); System.Trace("XYZ=" + wtX[weightCnt] + ", " + wtY[weightCnt] + ", " + wtZ[weightCnt]); } if ( weightCnt == numweights - 1) { //build mesh System.Trace("build the mesh"); dV = System.CreateDO("Space 3D Package/Vertex Stream Data"); dV.SetNumVertices(numverts); dV.BeginWrite(); for (vt = 0; vt < numverts ; vt++) { posX = 0; posY = 0; posZ = 0; wtCnt = weightElem[vt]; if (vt<2) System.Trace("weight count=" + wtCnt); fw = firstWeight[vt]; if (vt<2) System.Trace("first weight=" + fw); for (wt = 0; wt < wtCnt; wt++) { //find vertex from weight, weightXYZ, joint pos and joint quat //joint rotation matrix(quaternion) wi = fw + wt;//weight index jointIndex = wtJoint[wi]; if(vt<2) System.Trace("wi, joint index=" + wi + ", " + jointIndex); qx = xq[jointIndex]; qy = yq[jointIndex]; qz = zq[jointIndex]; qw = wq[jointIndex]; if(vt<2) System.Trace("xyzw=" + qx + ", " + qy + ", " + qz +", " + qw); rm11=1-2*qy*qy-2*qz*qz; rm12=2*qx*qy-2*qw*qz; rm13=2*qx*qz+2*qw*qy; rm21=2*qx*qy+2*qw*qz; rm22=1-2*qx*qx-2*qz*qz; rm23=2*qy*qz-2*qw*qx; rm31=2*qx*qz-2*qw*qy; rm32=2*qy*qz+2*qw*qx; rm33=1-2*qx*qx-2*qy*qy; // rm dot XYZ = rotated position rposX = rm11*wtX[wi] + rm21*wtY[wi] + rm31*wtZ[wi]; rposY = rm12*wtX[wi] + rm22*wtY[wi] + rm32*wtZ[wi]; rposZ = rm13*wtX[wi] + rm23*wtY[wi] + rm33*wtZ[wi]; posX = posX +(jx[jointIndex] + rposX)*weight[wi]; posY = posY +(jy[jointIndex] + rposY)*weight[wi]; posZ = posZ +(jz[jointIndex] + rposZ)*weight[wi]; } dV.x(vt) = posX * myScale; dV.y(vt) = posY * myScale; dV.z(vt) = posZ * myScale; //create cube at position of vertex posXYZ if (vt < 0) { curCube = Space.Cube(0.1, 0.1, 0.1, 1, 1, 1); Node.Value(curCube, "tx") = posX * myScale; Node.Value(curCube, "ty") = posY * myScale; Node.Value(curCube, "tz") = posZ * myScale; System.Trace("vert position = " + posX + ", " + posY + ", " + posZ); } } // verts done, triangles done try create TS mesh dV.EndWrite(); //test has 4 meshes only output the first one //if(curmesh==0) //{ dM = System.CreateDO("Space 3D Package/Mesh Data"); dM.AttachVerticesStream(dV); dM.AttachTrianglesStream(triface[curmesh]); dM.AttachCustStream(dT); //dM.SetTrianglesStreamGroup(UVTri[curmesh]); dM.AttachTrianglesStream(UVTri[curmesh]); //params.conValue('Mesh') = dM; Node.Value(encaps + "/doomShape","Mesh") = dM; //Node.ExportConnector(encaps + "/doomShape","Mesh","",1,1); //} } } // read joint data if (jointCnt != -1) { jointMesh[jointCnt] = Space.Cube(0.15, 0.15 ,0.15 ,1 ,1 ,1); msgtagSub = msgtag[0].split("\t"); jointName = msgtagSub[1].substr(1,msgtagSub[1].length-2); System.Trace(jointName); //System.Trace(jointMesh[jointCnt]); jointMesh[jointCnt] = Node.Rename(jointMesh[jointCnt], jointName); // create "joints" Node.Value(jointMesh[jointCnt], "tx") = msgtag[2]*myScale; Node.Value(jointMesh[jointCnt], "ty") = msgtag[3]*myScale; Node.Value(jointMesh[jointCnt], "tz") = msgtag[4]*myScale; Node.Copy(jointMesh[jointCnt], encaps); Node.Delete(jointMesh[jointCnt]); // save joint position - unscaled jx[jointCnt] = parseFloat(msgtag[2]); jy[jointCnt] = parseFloat(msgtag[3]); jz[jointCnt] = parseFloat(msgtag[4]); xq[jointCnt] = msgtag[7];//rotation of joint in quaternion form yq[jointCnt] = msgtag[8]; zq[jointCnt] = msgtag[9]; wq[jointCnt] = 1 - xq[jointCnt]*xq[jointCnt] - yq[jointCnt]*yq[jointCnt] - zq[jointCnt]*zq[jointCnt]; if (wq[jointCnt] < 0) { wq[jointCnt] = 0; } else { wq[jointCnt] = Math.sqrt(wq[jointCnt]) } jointCnt = jointCnt + 1; if (jointCnt == numJoints) { jointCnt = -1; } } if (msgtag[0] == "joints") { jointCnt = 0; //jointMesh[jointCnt] = Space.NURBSSphere(0.5); scene = Space.CurrentScene(); encapsO = Node.Create('Kernel Package/Object', scene);//create empty node in scene encaps = Node.Rename(encapsO, "doomSkeleton"); //transform node owner = System.ThisOwner(); Node.Copy(owner + "/doomTransform", encaps);//copy transform to new node Node.Rename(encaps + "/doomTransform", "Transform"); Node.ExportConnector(encaps + "/Transform","Matrix","",1,1); Node.ExportConnector(encaps + "/Transform","WldMatrix","",1,1); Node.ExportConnector(encaps + "/Transform","ObjMatrix","",1,1); Node.ExportConnector(encaps + "/Transform","OwnerMatrix","",1,1); } // vertex position is weighted sum of weights relative to the bone // need to use quat rotation of bone on point, weight it and add them together // weights add to a value of 1.0 // } System.Trace("end of import"); }