int LoadMapFiles(INode* node, SContext* sc, MtlBaseLib& mtls, TimeValue t) { NameTab mapFiles; CheckFileNames checkNames(&mapFiles); node->EnumAuxFiles(checkNames, FILE_ENUM_MISSING_ONLY | FILE_ENUM_1STSUB_MISSING); // Check the lights for (int i = 0; i < sc->lightTab.Count(); i++) { if (((LightInfo*)sc->lightTab[i])->light != NULL) { ((LightInfo*)sc->lightTab[i])->light->EnumAuxFiles(checkNames, FILE_ENUM_MISSING_ONLY | FILE_ENUM_1STSUB_MISSING); } } if (mapFiles.Count()) { // Error! Missing maps. // not sure how to handle this so we gladly continue. //if (MessageBox(hWnd, "There are missing maps.\nDo you want to render anyway?", "Warning!", MB_YESNO) != IDYES) { // return 0; //} } // Load the maps MapLoadEnum mapload(t); for (i=0; i<mtls.Count(); i++) { EnumMaps(mtls[i],-1, mapload); } return 1; }
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) { IfcGeom::IteratorSettings settings; settings.use_world_coords() = false; settings.weld_vertices() = true; settings.sew_shells() = true; #ifdef _UNICODE int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0); char* fn_mb = new char[fn_buffer_size]; WideCharToMultiByte(CP_UTF8, 0, name, -1, fn_mb, fn_buffer_size, 0, 0); #else const char* fn_mb = name; #endif IfcGeom::Iterator<float> iterator(settings, fn_mb); if (!iterator.initialize()) return false; itfc->ProgressStart(_T("Importing file..."), TRUE, fn, NULL); MtlBaseLib* mats = itfc->GetSceneMtls(); int slot = mats->Count(); std::map<std::vector<std::string>, Mtl*> material_cache; do{ const IfcGeom::TriangulationElement<float>* o = static_cast<const IfcGeom::TriangulationElement<float>*>(iterator.get()); TSTR o_type = S(o->type()); TSTR o_guid = S(o->guid()); Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->geometry().materials(), o->type(), o->geometry().material_ids()); TriObject* tri = CreateNewTriObject(); const int numVerts = o->geometry().verts().size()/3; tri->mesh.setNumVerts(numVerts); for( int i = 0; i < numVerts; i ++ ) { tri->mesh.setVert(i,o->geometry().verts()[3*i+0],o->geometry().verts()[3*i+1],o->geometry().verts()[3*i+2]); } const int numFaces = o->geometry().faces().size()/3; tri->mesh.setNumFaces(numFaces); bool needs_default = std::find(o->geometry().material_ids().begin(), o->geometry().material_ids().end(), -1) != o->geometry().material_ids().end(); typedef std::pair<int, int> edge_t; std::set<edge_t> face_boundaries; for(std::vector<int>::const_iterator it = o->geometry().edges().begin(); it != o->geometry().edges().end();) { const int v1 = *it++; const int v2 = *it++; const edge_t e((std::min)(v1, v2), (std::max)(v1, v2)); face_boundaries.insert(e); } for( int i = 0; i < numFaces; i ++ ) { const int v1 = o->geometry().faces()[3*i+0]; const int v2 = o->geometry().faces()[3*i+1]; const int v3 = o->geometry().faces()[3*i+2]; const edge_t e1((std::min)(v1, v2), (std::max)(v1, v2)); const edge_t e2((std::min)(v2, v3), (std::max)(v2, v3)); const edge_t e3((std::min)(v3, v1), (std::max)(v3, v1)); const bool b1 = face_boundaries.find(e1) != face_boundaries.end(); const bool b2 = face_boundaries.find(e2) != face_boundaries.end(); const bool b3 = face_boundaries.find(e3) != face_boundaries.end(); tri->mesh.faces[i].setVerts(v1, v2, v3); tri->mesh.faces[i].setEdgeVisFlags(b1, b2, b3); MtlID mtlid = o->geometry().material_ids()[i]; if (needs_default) { mtlid ++; } tri->mesh.faces[i].setMatID(mtlid); } tri->mesh.buildNormals(); // Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have // properly oriented normals. Using only the line below will result in a consistent // orientation of normals accross shells, but not always oriented towards the // outside. // tri->mesh.UnifyNormals(false); tri->mesh.BuildStripsAndEdges(); tri->mesh.InvalidateTopologyCache(); tri->mesh.InvalidateGeomCache(); ImpNode* node = impitfc->CreateNode(); node->Reference(tri); node->SetName(o_guid); node->GetINode()->Hide(o->type() == "IfcOpeningElement" || o->type() == "IfcSpace"); if (m) { node->GetINode()->SetMtl(m); } const std::vector<float>& matrix_data = o->transformation().matrix().data(); node->SetTransform(0,Matrix3 ( Point3(matrix_data[0],matrix_data[1],matrix_data[2]),Point3(matrix_data[3],matrix_data[4],matrix_data[5]), Point3(matrix_data[6],matrix_data[7],matrix_data[8]),Point3(matrix_data[9],matrix_data[10],matrix_data[11]) )); impitfc->AddNodeToScene(node); itfc->ProgressUpdate(iterator.progress(), true, _T("")); } while (iterator.next()); itfc->ProgressEnd(); return true; }
static IOResult ImportLibrary(ILoad* iload, MtlBaseLib& lib) { // Get the VIZ Importer/Exporter CComPtr<IVIZPointerClient> pPointerClient; HRESULT hr = CMaxMaterialCollection::GetXMLImpExp(&pPointerClient); if(hr != S_OK) return IO_ERROR; // Get the export interface CComQIPtr<IXmlMaterial> pIMtl = pPointerClient; ATLASSERT(pIMtl); if(!pIMtl) return IO_ERROR; // Create an XML document CComPtr<IXMLDOMDocument> doc; hr = doc.CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER); if (hr != S_OK || doc == NULL) return IO_ERROR; char* xmlStr = NULL; IOResult res = iload->ReadCStringChunk(&xmlStr); if (res != IO_OK) return res; if (xmlStr == NULL) return IO_OK; _bstr_t xml(xmlStr); VARIANT_BOOL result; hr = doc->loadXML(xml.GetBSTR(), &result); if (hr != S_OK || result == 0) return IO_ERROR; CComBSTR query = "./Materials/Material"; CComPtr<IXMLDOMNodeList> list; hr = doc->selectNodes(query, &list); if (hr != S_OK || list == NULL) return IO_ERROR; long i, len = 0; hr = list->get_length(&len); if (hr != S_OK) return IO_ERROR; long failed = 0; for (i = 0; i < len ; ++i) { CComPtr<IXMLDOMNode> node; hr = list->get_item(i, &node); if (hr == S_OK && node != NULL) { VARIANT vResult; vResult.vt = VT_BYREF; vResult.byref = NULL; hr = pIMtl->ImportMaterial(node, &vResult); if(SUCCEEDED(hr) && vResult.vt == VT_BYREF && vResult.byref != NULL) { lib.Add(static_cast<Mtl*>(vResult.byref)); } else ++failed; } } return failed == 0 ? IO_OK : IO_ERROR; }
//*************************************************************************** // Calculate ambient or diffuse color at each vertex. // Pass in TRUE as the "diffuse" parameter to calculate the diffuse color. // If FALSE is passed in, ambient color is calculated. //*************************************************************************** BOOL calcMixedVertexColors(INode* node, TimeValue t, int lightModel, ColorTab& vxColTab, EvalColProgressCallback* fn) { ObjectState ostate; BOOL deleteTri; Mesh* mesh; SContext sc; DefaultLight dl1, dl2; MtlBaseLib mtls; Matrix3 tm; sc.SetNodeAndTime(node, t); tm = sc.tmAfterWSM; TriObject* tri = GetTriObjectFromNode(node, t, deleteTri); // We will only work on GeomObjects if (!tri) { return FALSE; } // Get the mesh from the object mesh = &tri->GetMesh(); if (!mesh) { return FALSE; } // If the node doesn't have a material attached, // we create a dummy material. Mtl* mtl = node->GetMtl(); if (!mtl) { mtl = new DumMtl(Color(node->GetWireColor())); } mesh->buildRenderNormals(); vxColTab.ZeroCount(); vxColTab.Shrink(); sc.SetMesh(mesh); sc.CalcBoundObj(); // Add the material to the list mtls.AddMtl(mtl); // Setup ambient light if (lightModel == LIGHT_AMBIENT) { sc.SetAmbientLight(Color(1.0f, 1.0f, 1.0f)); } else { sc.SetAmbientLight(Color(0.0f, 0.0f, 0.0f)); } // If we're using the real lights, we need to find them first if (lightModel == LIGHT_SCENELIGHT) { AddSceneLights(&sc, &mtls); // Add default lights if there are no lights in the scene if (sc.lightTab.Count() == 0) { dl1.ls.intens = 1.0f; dl1.ls.color = Color(0.8f, 0.8f, 0.8f); dl1.ls.type = OMNI_LGT; dl1.tm = TransMatrix(1000.0f * Point3(-900.0f, -1000.0f, 1500.0f)); dl2.ls.intens = 1.0f; dl2.ls.color = Color(0.8f, 0.8f, 0.8f); dl2.ls.type = OMNI_LGT; dl2.tm = TransMatrix(-1000.0f * Point3(-900.0f, -1000.0f, 1500.0f)); sc.AddLight(new LightInfo(&dl1)); sc.AddLight(new LightInfo(&dl2)); } sc.SetAmbientLight(GetCOREInterface()->GetAmbient(t, FOREVER)); } sc.UpdateLights(); // Update material mtl->Update(t, FOREVER); int numVerts = mesh->numVerts; for (unsigned int v = 0; v < (unsigned)numVerts; v++) { if (fn) { if (fn->progress(float(v)/float(numVerts))) { if (deleteTri) { delete tri; } mtls.Empty(); if (mtl->ClassID() == DUMMTL_CLASS_ID) { delete mtl; } // What to return here is up for discussion. // 1) We are aborting so FALSE might be in order. // 2) We have calculated some colors. Let's use what we've got so far. return TRUE; } } // Create a new entry Color* vxCol = new Color; Point3 tmpCol(0.0f, 0.0f, 0.0f); int numShades = 0; BitArray faceList; faceList.SetSize(mesh->numFaces, 0); // Get vertex normal // We also pass in a BitArray that will be filled in with // to inform us to which faces this vertex belongs. // We could do this manually, but we need to do it to get // the vertex normal anyway so this is done to speed things // up a bit. Point3 vxNormal = interpVertexNormal(mesh, tm, v, faceList); Point3 viewDir = -vxNormal; Point3 viewPoint = tm*mesh->verts[v] + 5.0f*vxNormal; Point3 lightPos = viewPoint; Point3 viewTarget = tm*mesh->verts[v]; // We now have a viewpoint and a view target. // Now we just have to shade this point on the mesh in order // to get it's color. // Note: // Since materials are assigned on Face basis we need to render each // vertex as many times as it has connecting faces. // the colors collected are mixed to get the resulting // color at each vertex. for (int nf = 0; nf < faceList.GetSize(); nf++) { if (faceList[nf]) { // render vertex for this face. sc.SetViewPoint(viewPoint); sc.SetTargetPoint(viewTarget); sc.SetViewDir(viewDir); sc.SetFaceNum(nf); Face* f = &mesh->faces[nf]; sc.SetMtlNum(f->getMatID()); sc.CalcNormals(); // Setup the barycentric coordinate if (mesh->faces[nf].v[0] == v) sc.SetBaryCoord(Point3(1.0f, 0.0f, 0.0f)); else if (mesh->faces[nf].v[1] == v) sc.SetBaryCoord(Point3(0.0f, 1.0f, 0.0f)); else if (mesh->faces[nf].v[2] == v) sc.SetBaryCoord(Point3(0.0f, 0.0f, 1.0f)); // Use diffuse color instead of ambient // The only difference is that we create a special light // located at the viewpoint and we set the ambient light to black. if (lightModel == LIGHT_DIFFUSE) { dl1.ls.intens = 1.0f; dl1.ls.color = Color(0.8f, 0.8f, 0.8f); dl1.ls.type = OMNI_LGT; dl1.tm = TransMatrix(lightPos); sc.ClearLights(); sc.AddLight(new LightInfo(&dl1)); sc.UpdateLights(); } // Shade the vertex mtl->Shade(sc); tmpCol.x += sc.out.c.r; tmpCol.y += sc.out.c.g; tmpCol.z += sc.out.c.b; numShades++; } } // The color mixes. We just add the colors together and // then divide with as many colors as we added. if (numShades > 0) { tmpCol = tmpCol / (float)numShades; } vxCol->r = tmpCol.x; vxCol->g = tmpCol.y; vxCol->b = tmpCol.z; vxCol->ClampMinMax(); // Append the Color to the table. If the array needs // to be realloc'ed, allocate extra space for 100 points. vxColTab.Append(1, &vxCol, 100); } // Some objects gives us a temporary mesh that we need to delete afterwards. if (deleteTri) { delete tri; } mtls.Empty(); if (mtl->ClassID() == DUMMTL_CLASS_ID) { delete mtl; } return TRUE; }
int GetMaps::proc(ReferenceMaker *rm) { if (IsTex((MtlBase*)rm)) mlib->AddMtl((MtlBase *)rm); return REF_ENUM_CONTINUE; }
void GetMaps::proc(ReferenceMaker *rm) { if (IsTex((MtlBase*)rm)) { mlib->AddMtl((MtlBase *)rm); } }