bool NifImporter::ImportMesh(NiTriShapeRef triShape) { bool ok = true; ImpNode *node = i->CreateNode(); if(!node) return false; TriObject *triObject = CreateNewTriObject(); node->Reference(triObject); wstring name = wide(triShape->GetName()); node->SetName(name.c_str()); INode *inode = node->GetINode(); imports.push_back(inode); // Texture Mesh& mesh = triObject->GetMesh(); NiTriShapeDataRef triShapeData = DynamicCast<NiTriShapeData>(triShape->GetData()); if (triShapeData == NULL) return false; vector<Triangle> tris = triShapeData->GetTriangles(); ok |= ImportMesh(node, triObject, triShape, triShapeData, tris); return ok; }
/*---------------------------------------------------------------------------*/ NiTriShapeRef NifConvertUtility::convertNiTriStrips(NiTriStripsRef pSrcNode, NiTriShapeRef pTmplNode, NiAlphaPropertyRef pTmplAlphaProp) { NiTriShapeRef pDstNode (new NiTriShape()); NiTriShapeDataRef pDstGeo (new NiTriShapeData()); NiTriStripsDataRef pSrcGeo (DynamicCast<NiTriStripsData>(pSrcNode->GetData())); vector<NiPropertyRef> srcPropList(pSrcNode->GetProperties()); // copy NiTriStrips to NiTriShape pDstNode->SetCollisionObject(NULL); // no collision object here pDstNode->SetFlags (14); // ??? pDstNode->SetName (pSrcNode->GetName()); pDstNode->SetLocalTransform (pSrcNode->GetLocalTransform()); pDstNode->SetData (pDstGeo); // move properties for (auto pIter=srcPropList.begin(), pEnd=srcPropList.end(); pIter != pEnd; ++pIter) { if (DynamicCast<NiVertexColorProperty>(*pIter) != NULL) { int iii=0; } pDstNode->AddProperty(*pIter); } pSrcNode->ClearProperties(); // data node if (pSrcGeo != NULL) { pDstGeo->SetVertices (pSrcGeo->GetVertices()); pDstGeo->SetNormals (pSrcGeo->GetNormals()); pDstGeo->SetTriangles (pSrcGeo->GetTriangles()); pDstGeo->SetVertexColors(pSrcGeo->GetColors()); pDstGeo->SetUVSetCount (pSrcGeo->GetUVSetCount()); for (short idx(0), max(pSrcGeo->GetUVSetCount()); idx < max; ++idx) { pDstGeo->SetUVSet(idx, pSrcGeo->GetUVSet(idx)); } } // if (pSrcGeo != NULL) // return converted NiTriShape return convertNiTri(pDstNode, pTmplNode, pTmplAlphaProp); }
void addToNif(Land l, long offx, long offy, CellMeshList& cml){ using namespace Niflib; std::vector<Vector3> verts; std::vector<Vector3> normals; std::vector<TexCoord> txCoords; std::vector<Triangle> tris; for ( int x = 0; x < 65; x++){ for ( int y = 0; y < 65; y++){ verts.push_back( Vector3(x*128,y*128,l.land[x][y]*8) ); //vector needs to be normalized float nx = l.normals[x][y].x; float ny = l.normals[x][y].y; float nz = l.normals[x][y].z; float mag = sqrt(nx*nx+ny*ny+nz*nz); nx/=mag; ny/=mag; nz/=mag; normals.push_back( Vector3(nx,ny,nz) ); txCoords.push_back( TexCoord(x/(float)65, y/(float)65) ); } } //ak. Hacky const unsigned vertNum = 65 * 65; const unsigned meshLength = sqrt((float) vertNum); const unsigned loopSize = (vertNum) - (meshLength * 2) + 65; for( unsigned i = 0; i < loopSize; i++){ unsigned iTmp = i; while ( iTmp > (meshLength - 1) ) iTmp -= meshLength; if ( iTmp == (meshLength - 1) ) continue; Triangle tri; tri.v1 = i; tri.v2 = i + meshLength; tri.v3 = i + 1; tris.push_back(tri); tri.v1 = i + meshLength; tri.v2 = i + meshLength + 1; tri.v3 = i + 1; tris.push_back(tri); } NiTriShapeRef shape = new NiTriShape; shape->SetName("TxtMesh"); shape->AddProperty(getMatProp()); shape->AddProperty(getTexture()); NiTriShapeDataRef triData = new NiTriShapeData; triData->SetVertices(verts); triData->SetNormals(normals); triData->SetTriangles(tris); //uv triData->SetUVSetCount(1); triData->SetUVSet(0, txCoords); //ad it to the TriShape NiGeometryDataRef gRef = DynamicCast<NiGeometryData>( triData ); shape->SetData(gRef); NiAVObjectRef avObj = DynamicCast<NiAVObject>( shape ); //make it so the center of the cell is on 0, 0 Vector3 vec3; vec3.x = offx; vec3.y = offy; avObj->SetLocalTranslation(vec3); cml.push_back(avObj); }
MeshData *CMesh::AddTriShape(NiTriShapeRef trishapenode) { unsigned long index; MeshData *newmeshpart; MeshVertex *davert; unsigned short *daind; if(trishapenode==NULL) return NULL; NiGeometryDataRef ergeom = trishapenode->GetData(); NiTriShapeDataRef geom = DynamicCast<NiTriShapeData>(ergeom); if(geom==NULL) { output_text(L"Couldn't cast to NiTriStripsData!\r\n"); return NULL; } if(geom->GetUVSetCount()==0||geom->GetTriangles().size()==0) { if(geom->GetUVSetCount()==0) output_text_hex(L"No UV Set:",formID); if(geom->GetTriangles().size()==0) output_text_hex(L"No Triangles:",formID); return NULL; } //Get the vertices vector<Vector3> davertices=geom->GetVertices(); //Get the uvs vector<TexCoord> dauvs=geom->GetUVSet(0); //Get the normals vector<Vector3> danormals=geom->GetNormals(); //Get the colors vector<Color4> dacolors=geom->GetColors(); //Get the indices vector<Triangle> daindices=geom->GetTriangles(); newmeshpart=new MeshData; //Get the number of vertex newmeshpart->numvert=geom->GetVertexCount(); //Get the number of indices newmeshpart->numind=daindices.size()*3; //newmeshpart->numind=geom->GetVertexIndexCount(); //output_text_value(L"Number of vertex:",newmeshpart->numvert); //output_text_value(L"Number of indices:",newmeshpart->numind); if(newmeshpart->numvert==0||newmeshpart->numind==0) { if(newmeshpart->numvert==0) output_text_hex(L"No vertex?:",formID); if(newmeshpart->numind==0) output_text_hex(L"No indices?:",formID); delete newmeshpart; return NULL; } davert=new MeshVertex[newmeshpart->numvert]; daind=new unsigned short[newmeshpart->numind]; for(index=0;index<(newmeshpart->numind/3);index++) { //memcpy later //daind[index]=daindices[(newmeshpart->numind-1)-index]; daind[index*3]=daindices[index].v1; daind[(index*3)+1]=daindices[index].v2; daind[(index*3)+2]=daindices[index].v3; } for(index=0;index<newmeshpart->numvert;index++) { //change to use memcpy later davert[index].Pos.x=davertices[index].x; davert[index].Pos.y=davertices[index].y; davert[index].Pos.z=davertices[index].z; davert[index].TextUV.x=dauvs[index].u; davert[index].TextUV.y=dauvs[index].v; davert[index].Norm.x=danormals[index].x; davert[index].Norm.y=danormals[index].y; davert[index].Norm.z=danormals[index].z; } if(dacolors.size()!=0) { for(index=0;index<newmeshpart->numvert;index++) { davert[index].Color.x=dacolors[index].r; davert[index].Color.y=dacolors[index].g; davert[index].Color.z=dacolors[index].b; davert[index].Color.w=dacolors[index].a; } } else { for(index=0;index<newmeshpart->numvert;index++) { davert[index].Color.x=1.0f; davert[index].Color.y=1.0f; davert[index].Color.z=1.0f; davert[index].Color.w=1.0f; } } //Load the texture vector<NiPropertyRef> daprops=trishapenode->GetProperties(); bool foundtext=false; for(index=0;index<daprops.size();index++) { if(daprops[index]->IsSameType(NiTexturingProperty::TYPE)) { NiTexturingPropertyRef datextprop=DynamicCast<NiTexturingProperty>(daprops[index]); if(datextprop==NULL) { output_text(L"Failed NiTexturingProperty Cast!\r\n"); delete newmeshpart; delete [] davert; delete [] daind; return NULL; } foundtext=true; TexDesc datextdesc=datextprop->GetTexture(0); newmeshpart->datext=pTextureManager->Load_Direct((char *)datextdesc.source->GetTextureFileName().c_str()); break; } } if(foundtext==false) output_text_hex(L"Couldn't find texture:",formID); newmeshpart->pIndiceBuf=pDXManager->CreateIndiceBuffer((unsigned char *)daind,newmeshpart->numind,sizeof(unsigned short)); newmeshpart->pVertexBuf=pDXManager->CreateVertexBuffer((unsigned char *)davert,newmeshpart->numvert,sizeof(MeshVertex)); delete [] daind; delete [] davert; //Ok now let's add it listdata.push_back(newmeshpart); return newmeshpart; }
/*---------------------------------------------------------------------------*/ bool NifConvertUtility::updateTangentSpace(NiTriShapeDataRef pDataObj) { vector<Vector3> vecVertices (pDataObj->GetVertices()); vector<Vector3> vecNormals (pDataObj->GetNormals()); if(vecVertices.size() > 0 && ! pDataObj->GetUVSetCount() ) { logMessage(NCU_MSG_TYPE_INFO, "UpdateTangentSpace: has vertices but not UV"); return false; } vector<TexCoord> vecTexCoords(pDataObj->GetUVSet(0) ); vector<Triangle> vecTriangles(pDataObj->GetTriangles()); // check on valid input data if (vecVertices.empty() || vecTriangles.empty() || vecNormals.size() != vecVertices.size() || vecVertices.size() != vecTexCoords.size()) { logMessage(NCU_MSG_TYPE_INFO, "UpdateTangentSpace: No vertices, normals, coords or faces defined."); return false; } // prepare result vectors vector<Vector3> vecTangents = vector<Vector3>(vecVertices.size(), Vector3(0.0f, 0.0f, 0.0f)); vector<Vector3> vecBiNormals = vector<Vector3>(vecVertices.size(), Vector3(0.0f, 0.0f, 0.0f)); for (unsigned int t(0); t < vecTriangles.size(); ++t) { Vector3 vec21(vecVertices[vecTriangles[t][1]] - vecVertices[vecTriangles[t][0]]); Vector3 vec31(vecVertices[vecTriangles[t][2]] - vecVertices[vecTriangles[t][0]]); TexCoord txc21(vecTexCoords[vecTriangles[t][1]] - vecTexCoords[vecTriangles[t][0]]); TexCoord txc31(vecTexCoords[vecTriangles[t][2]] - vecTexCoords[vecTriangles[t][0]]); float radius(((txc21.u * txc31.v - txc31.u * txc21.v) >= 0.0f ? +1.0f : -1.0f)); Vector3 sdir(( txc31.v * vec21[0] - txc21.v * vec31[0] ) * radius, ( txc31.v * vec21[1] - txc21.v * vec31[1] ) * radius, ( txc31.v * vec21[2] - txc21.v * vec31[2] ) * radius); Vector3 tdir(( txc21.u * vec31[0] - txc31.u * vec21[0] ) * radius, ( txc21.u * vec31[1] - txc31.u * vec21[1] ) * radius, ( txc21.u * vec31[2] - txc31.u * vec21[2] ) * radius); // normalize sdir = sdir.Normalized(); tdir = tdir.Normalized(); for (int j(0); j < 3; ++j) { vecTangents [vecTriangles[t][j]] += tdir; vecBiNormals[vecTriangles[t][j]] += sdir; } } // for (unsigned int t(0); t < vecTriangles.size(); ++t) for (unsigned int i(0); i < vecVertices.size(); ++i) { Vector3& n(vecNormals[i]); Vector3& t(vecTangents [i]); Vector3& b(vecBiNormals[i]); if ((t == Vector3()) || (b == Vector3())) { t[0] = n[1]; t[1] = n[2]; t[2] = n[0]; b = n.CrossProduct(t); } else { t = t.Normalized(); t = (t - n * n.DotProduct(t)); t = t.Normalized(); b = b.Normalized(); b = (b - n * n.DotProduct(b)); b = (b - t * t.DotProduct(b)); b = b.Normalized(); } } // for (unsigned int i(0); i < vecVertices.size(); ++i) // set tangents and binormals to object pDataObj->SetBitangents(vecBiNormals); pDataObj->SetTangents (vecTangents); return true; }