void SolidifyPW::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { //TODO: Add the code for actually modifying the object meshInfo.Free(); if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; float a,oa; pblock->GetValue(pb_amount,t,a,iv); pblock->GetValue(pb_oamount,t,oa,iv); if (a == oa) oa += 0.00001f; BOOL overrideMatID; int matid; pblock->GetValue(pb_overridematid,t,overrideMatID,iv); pblock->GetValue(pb_matid,t,matid,iv); matid--; if (!overrideMatID) matid = -1; BOOL overridesg; int sg; pblock->GetValue(pb_overridesg,t,overridesg,iv); pblock->GetValue(pb_sg,t,sg,iv); if (!overridesg) sg = -1; int edgeMap; pblock->GetValue(pb_edgemap,t,edgeMap,iv); float tvOffset; pblock->GetValue(pb_tvoffset,t,tvOffset,iv); BOOL ioverrideMatID; int imatid; pblock->GetValue(pb_overrideinnermatid,t,ioverrideMatID,iv); pblock->GetValue(pb_innermatid,t,imatid,iv); imatid--; if (!ioverrideMatID) imatid = -1; BOOL ooverrideMatID; int omatid; pblock->GetValue(pb_overrideoutermatid,t,ooverrideMatID,iv); pblock->GetValue(pb_outermatid,t,omatid,iv); omatid--; if (!ooverrideMatID) omatid = -1; BOOL selEdges, selInner,selOuter; static BOOL selEdgesPrev = FALSE; static BOOL selInnerPrev = FALSE; static BOOL selOuterPrev = FALSE; BOOL updateUI = FALSE; pblock->GetValue(pb_seledges,t,selEdges,iv); pblock->GetValue(pb_selinner,t,selInner,iv); pblock->GetValue(pb_selouter,t,selOuter,iv); if (selEdges && (!selEdgesPrev)) updateUI = TRUE; if (selInner && (!selInnerPrev)) updateUI = TRUE; if (selOuter && (!selOuterPrev)) updateUI = TRUE; selEdgesPrev = selEdges; selInnerPrev = selInner; selOuterPrev = selOuter; if (selEdges || selInner|| selOuter) { mesh.dispFlags = DISP_SELFACES; mesh.selLevel = MESH_FACE; } int segments = 1; pblock->GetValue(pb_segments,t,segments,iv); if (segments < 1) segments = 1; BOOL fixupCorners; pblock->GetValue(pb_fixupcorners,t,fixupCorners,iv); BOOL autoSmooth; float smoothAngle; pblock->GetValue(pb_autosmooth,t,autoSmooth,iv); pblock->GetValue(pb_autosmoothangle,t,smoothAngle,iv); BOOL bevel; INode *node; pblock->GetValue(pb_bevel,t,bevel,iv); pblock->GetValue(pb_bevelshape,t,node,iv); PolyShape shape; if ((bevel) && node) { ObjectState nos = node->EvalWorldState(t); if (nos.obj->IsShapeObject()) { ShapeObject *pathOb = (ShapeObject*)nos.obj; if (!pathOb->NumberOfCurves()) { bevel = FALSE; } else { pathOb->MakePolyShape(t, shape,PSHAPE_BUILTIN_STEPS,TRUE); if (shape.lines[0].IsClosed()) bevel = FALSE; ; } } } DWORD selLevel = mesh.selLevel; mesh.faceSel.ClearAll(); if (bevel) meshInfo.MakeSolid(&mesh,segments, a,oa,matid, sg,edgeMap,tvOffset,imatid,omatid,selEdges,selInner,selOuter,fixupCorners,autoSmooth,smoothAngle,&shape.lines[0]); else meshInfo.MakeSolid(&mesh,segments, a,oa,matid, sg,edgeMap,tvOffset,imatid,omatid,selEdges,selInner,selOuter,fixupCorners,autoSmooth,smoothAngle,NULL); mesh.selLevel = selLevel; mesh.InvalidateTopologyCache (); for (int i = 0; i < mesh.numFaces; i++) { for (int j = 0; j < 3; j++) { int index = mesh.faces[j].v[j]; if ((index < 0) || (index >= mesh.numVerts)) DebugPrint(_T("Invalid face %d(%d) %d\n"),i,j,index); } } int numMaps = mesh.getNumMaps(); for (int mp = -NUM_HIDDENMAPS; mp < numMaps; mp++) { if (!mesh.mapSupport(mp)) continue; Point3 *uvw = mesh.mapVerts(mp); TVFace *uvwFace = mesh.mapFaces(mp); if ((uvw) && (uvwFace)) { int numberTVVerts = mesh.getNumMapVerts(mp); for (int i = 0; i < mesh.numFaces; i++) { for (int j = 0; j < 3; j++) { int index = uvwFace[i].t[j]; if ((index < 0) || (index >= numberTVVerts)) DebugPrint(_T("Invalid Map %d tvface %d(%d) %d\n"),mp,i,j,index); } } } } os->obj->UpdateValidity(GEOM_CHAN_NUM,iv); os->obj->UpdateValidity(TOPO_CHAN_NUM,iv); MeshNormalSpec *pNormSpec = (MeshNormalSpec *) mesh.GetInterface (MESH_NORMAL_SPEC_INTERFACE); if (pNormSpec && pNormSpec->GetNumFaces() > 0) { pNormSpec->SetParent(&mesh); pNormSpec->BuildNormals(); pNormSpec->ComputeNormals(); } if ((updateUI) && (ip)) { ip->PipeSelLevelChanged(); } } EnableUIControls(); }
bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeomRef>& glist) { bool ok = true; if (glist.empty()) return false; ImpNode *node = i->CreateNode(); if(!node) return false; INode *inode = node->GetINode(); TriObject *triObject = CreateNewTriObject(); node->Reference(triObject); string name = parent->GetName(); node->SetName(wide(name).c_str()); // Texture Mesh& mesh = triObject->GetMesh(); vector< pair<int, int> > vert_range, tri_range; vector<Triangle> tris; vector<Vector3> verts; int submats = glist.size(); // Build list of vertices and triangles. Optional components like normals will be handled later. for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) { NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData()); // Get verts and collapse local transform into them int nVertices = triGeomData->GetVertexCount(); vector<Vector3> subverts = triGeomData->GetVertices(); Matrix44 transform = (*itr)->GetLocalTransform(); //Apply the transformations if (transform != Matrix44::IDENTITY) { for ( unsigned int i = 0; i < subverts.size(); ++i ) subverts[i] = transform * subverts[i]; } vert_range.push_back( pair<int,int>( verts.size(), verts.size() + subverts.size()) ); verts.insert(verts.end(), subverts.begin(), subverts.end()); vector<Triangle> subtris = triGeomData->GetTriangles(); for (vector<Triangle>::iterator itr = subtris.begin(), end = subtris.end(); itr != end; ++itr) { (*itr).v1 += nVertices, (*itr).v2 += nVertices, (*itr).v3 += nVertices; } tri_range.push_back( pair<int,int>( tris.size(), tris.size() + subtris.size()) ); tris.insert(tris.end(), subtris.begin(), subtris.end()); } // Transform up-to-parent Matrix44 baseTM = (importBones) ? Matrix44::IDENTITY : parent->GetWorldTransform(); node->SetTransform(0,TOMATRIX3(baseTM)); // Set vertices and triangles mesh.setNumVerts(verts.size()); mesh.setNumTVerts(verts.size(), TRUE); for (int i=0, n=verts.size(); i < n; ++i){ Vector3 &v = verts[i]; mesh.verts[i].Set(v.x, v.y, v.z); } mesh.setNumFaces(tris.size()); mesh.setNumTVFaces(tris.size()); for (int submat=0; submat<submats; ++submat) { int t_start = tri_range[submat].first, t_end = tri_range[submat].second; for (int i=t_start; i<t_end; ++i) { Triangle& t = tris[i]; Face& f = mesh.faces[i]; f.setVerts(t.v1, t.v2, t.v3); f.Show(); f.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS); f.setMatID(-1); TVFace& tf = mesh.tvFace[i]; tf.setTVerts(t.v1, t.v2, t.v3); } } mesh.buildNormals(); bool bSpecNorms = false; MultiMtl *mtl = NULL; int igeom = 0; for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr, ++igeom) { NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData()); int v_start = vert_range[igeom].first, v_end = vert_range[igeom].second; int t_start = tri_range[igeom].first, t_end = tri_range[igeom].second; // Normals vector<Vector3> subnorms = triGeomData->GetNormals(); Matrix44 rotation = (*itr)->GetLocalTransform().GetRotation(); if (rotation != Matrix44::IDENTITY) { for ( unsigned int i = 0; i < subnorms.size(); ++i ) subnorms[i] = rotation * subnorms[i]; } if (!subnorms.empty()) { #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 // Initialize normals if necessary if (!bSpecNorms) { bSpecNorms = true; mesh.SpecifyNormals(); MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (NULL != specNorms) { specNorms->BuildNormals(); //specNorms->ClearAndFree(); //specNorms->SetNumFaces(tris.size()); //specNorms->SetNumNormals(n.size()); } } MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (NULL != specNorms) { Point3* norms = specNorms->GetNormalArray(); for (int i=0, n=subnorms.size(); i<n; i++){ Vector3& v = subnorms[i]; norms[i+v_start] = Point3(v.x, v.y, v.z); } //MeshNormalFace* pFaces = specNorms->GetFaceArray(); //for (int i=0; i<tris.size(); i++){ // Triangle& tri = tris[i]; // MeshNormalFace& face = pFaces[i+t_start]; // face.SpecifyNormalID(0, tri.v1); // face.SpecifyNormalID(1, tri.v2); // face.SpecifyNormalID(2, tri.v3); //} #if VERSION_3DSMAX > ((7000<<16)+(15<<8)+0) // Version 7+ specNorms->SetAllExplicit(true); #endif specNorms->CheckNormals(); } #endif } // uv texture info if (triGeomData->GetUVSetCount() > 0) { vector<TexCoord> texCoords = triGeomData->GetUVSet(0); for (int i=0, n = texCoords.size(); i<n; ++i) { TexCoord& texCoord = texCoords[i]; mesh.tVerts[i+v_start].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0); } } vector<Color4> cv = triGeomData->GetColors(); ImportVertexColor(inode, triObject, tris, cv, v_start); if ( StdMat2* submtl = ImportMaterialAndTextures(node, (*itr)) ) { if (mtl == NULL) { mtl = NewDefaultMultiMtl(); gi->GetMaterialLibrary().Add(mtl); inode->SetMtl(mtl); } // SubMatIDs do not have to be contiguous so we just use the offset mtl->SetSubMtlAndName(igeom, submtl, submtl->GetName()); for (int i=t_start; i<t_end; ++i) mesh.faces[i].setMatID(igeom); } if (enableSkinSupport) ImportSkin(node, (*itr)); } this->i->AddNodeToScene(node); inode = node->GetINode(); inode->EvalWorldState(0); for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) { // attach child if (INode *parent = GetNode((*itr)->GetParent())) parent->AttachChild(inode, 1); inode->Hide((*itr)->GetVisibility() ? FALSE : TRUE); } if (removeDegenerateFaces) mesh.RemoveDegenerateFaces(); if (removeIllegalFaces) mesh.RemoveIllegalFaces(); if (weldVertices) WeldVertices(mesh); if (enableAutoSmooth) mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE); return ok; }