bool CEditableObject::Import_LWO(const char* fn, bool bNeedOptimize) { lwObject *I=0; // UI->SetStatus("Importing..."); // UI->ProgressStart(100,"Read file:"); // UI->ProgressUpdate(1); string512 fname; strcpy(fname,fn); #ifdef _EDITOR I=LWO_ImportObject(fname,I); #else unsigned int failID; int failpos; I = lwGetObject( fname, &failID, &failpos ); #endif // UI->ProgressUpdate(100); if (I){ bool bResult=true; ELog.Msg( mtInformation, "CEditableObject: import lwo %s...", fname ); // parse lwo object { m_Meshes.reserve (I->nlayers); m_Surfaces.reserve (I->nsurfs); // surfaces st_lwSurface* Isf=0; { int i=0; // UI->ProgressStart(I->nsurfs,"Check surf:"); for (Isf=I->surf; Isf; Isf=Isf->next){ // UI->ProgressUpdate(i); Isf->alpha_mode=i; // перетираем для внутренних целей !!! CSurface* Osf = new CSurface(); m_Surfaces.push_back(Osf); if (Isf->name&&Isf->name[0]) Osf->SetName(Isf->name); else Osf->SetName("Default"); Osf->m_Flags.set(CSurface::sf2Sided,(Isf->sideflags==3)?TRUE:FALSE); AnsiString en_name="default", lc_name="default", gm_name="default"; XRShader* sh_info = 0; if (Isf->nshaders&&(stricmp(Isf->shader->name,SH_PLUGIN_NAME)==0)){ sh_info = (XRShader*)Isf->shader->data; en_name = sh_info->en_name; lc_name = sh_info->lc_name; gm_name = sh_info->gm_name; }else ELog.Msg(mtError,"CEditableObject: Shader not found on surface '%s'.",Osf->_Name()); #ifdef _EDITOR if (!Device.Resources->_FindBlender(en_name.c_str())){ ELog.Msg(mtError,"CEditableObject: Render shader '%s' - can't find in library.\nUsing 'default' shader on surface '%s'.", en_name.c_str(), Osf->_Name()); en_name = "default"; } if (!Device.ShaderXRLC.Get(lc_name.c_str())){ ELog.Msg(mtError,"CEditableObject: Compiler shader '%s' - can't find in library.\nUsing 'default' shader on surface '%s'.", lc_name.c_str(), Osf->_Name()); lc_name = "default"; } if (!GMLib.GetMaterial(gm_name.c_str())){ ELog.Msg(mtError,"CEditableObject: Game material '%s' - can't find in library.\nUsing 'default' material on surface '%s'.", lc_name.c_str(), Osf->_Name()); gm_name = "default"; } #endif // fill texture layers int cidx; st_lwClip* Icl; u32 dwNumTextures=0; for (st_lwTexture* Itx=Isf->color.tex; Itx; Itx=Itx->next){ string1024 tname=""; dwNumTextures++; cidx = -1; if (Itx->type==ID_IMAP) cidx=Itx->param.imap.cindex; else{ ELog.DlgMsg(mtError, "Import LWO (Surface '%s'): 'Texture' is not Image Map!",Osf->_Name()); bResult=false; break; } if (cidx!=-1){ // get textures for (Icl=I->clip; Icl; Icl=Icl->next) if ((cidx==Icl->index)&&(Icl->type==ID_STIL)){ strcpy(tname,Icl->source.still.name); break; } if (tname[0]==0){ ELog.DlgMsg(mtError, "Import LWO (Surface '%s'): 'Texture' name is empty or non 'STIL' type!",Osf->_Name()); bResult=false; break; } string256 tex_name; _splitpath( tname, 0, 0, tex_name, 0 ); Osf->SetTexture(EFS.AppendFolderToName(tex_name,1,TRUE)); // get vmap refs Osf->SetVMap(Itx->param.imap.vmap_name); } } if (!bResult) break; if (!Osf->_VMap()||!Osf->_VMap()[0]){ ELog.DlgMsg(mtError, "Invalid surface '%s'. VMap empty.",Osf->_Name()); bResult = false; break; } if (!Osf->_Texture()||!Osf->_Texture()[0]){ ELog.DlgMsg(mtError, "Can't create shader. Invalid surface '%s'. Textures empty.",Osf->_Name()); bResult = false; break; } if (en_name.c_str()==0){ ELog.DlgMsg(mtError, "Can't create shader. Invalid surface '%s'. Shader empty.",Osf->_Name()); bResult = false; break; } Osf->SetShader (en_name.c_str()); Osf->SetShaderXRLC (lc_name.c_str()); Osf->SetGameMtl (gm_name.c_str()); Osf->SetFVF (D3DFVF_XYZ|D3DFVF_NORMAL|(dwNumTextures<<D3DFVF_TEXCOUNT_SHIFT)); i++; } } if (bResult){ // mesh layers st_lwLayer* Ilr=0; int k=0; for (Ilr=I->layer; Ilr; Ilr=Ilr->next){ // create new mesh CEditableMesh* MESH= new CEditableMesh(this); m_Meshes.push_back(MESH); if (Ilr->name) MESH->SetName(Ilr->name); else MESH->SetName(""); MESH->m_Box.set(Ilr->bbox[0],Ilr->bbox[1],Ilr->bbox[2], Ilr->bbox[3],Ilr->bbox[4],Ilr->bbox[5]); // parse mesh(lwo-layer) data // vmaps st_lwVMap* Ivmap=0; int vmap_count=0; if (Ilr->nvmaps==0){ ELog.DlgMsg(mtError, "Import LWO: Mesh layer must contain UV!"); bResult=false; break; } // индексы соответствия импортируемых мап static VMIndexLink VMIndices; VMIndices.clear(); for (Ivmap=Ilr->vmap; Ivmap; Ivmap=Ivmap->next){ switch(Ivmap->type){ case ID_TXUV:{ if (Ivmap->dim!=2){ ELog.DlgMsg(mtError, "Import LWO: 'UV Map' must contain 2 value!"); bResult=false; break; } MESH->m_VMaps.push_back(new st_VMap(Ivmap->name,vmtUV,!!Ivmap->perpoly)); st_VMap* Mvmap=MESH->m_VMaps.back(); int vcnt=Ivmap->nverts; // VMap Mvmap->copyfrom(*Ivmap->val,vcnt); // flip uv for (int k=0; k<Mvmap->size(); k++){ Fvector2& uv = Mvmap->getUV(k); uv.y=1.f-uv.y; } // vmap index VMIndices[Ivmap] = vmap_count++; }break; case ID_WGHT:{ if (Ivmap->dim!=1){ ELog.DlgMsg(mtError, "Import LWO: 'Weight' must contain 1 value!"); bResult=false; break; } MESH->m_VMaps.push_back(new st_VMap(Ivmap->name,vmtWeight,false)); st_VMap* Mvmap=MESH->m_VMaps.back(); int vcnt=Ivmap->nverts; // VMap Mvmap->copyfrom(*Ivmap->val,vcnt); // vmap index VMIndices[Ivmap] = vmap_count++; }break; case ID_PICK: ELog.Msg(mtError,"Found 'PICK' VMAP. Import failed."); bResult = false; break; case ID_MNVW: ELog.Msg(mtError,"Found 'MNVW' VMAP. Import failed."); bResult = false; break; case ID_MORF: ELog.Msg(mtError,"Found 'MORF' VMAP. Import failed."); bResult = false; break; case ID_SPOT: ELog.Msg(mtError,"Found 'SPOT' VMAP. Import failed."); bResult = false; break; case ID_RGB: ELog.Msg(mtError,"Found 'RGB' VMAP. Import failed."); bResult = false; break; case ID_RGBA: ELog.Msg(mtError,"Found 'RGBA' VMAP. Import failed."); bResult = false; break; } if (!bResult) break; } if (!bResult) break; // points // UI->ProgressStart(Ilr->point.count,"Fill points:"); { MESH->m_VertCount = Ilr->point.count; MESH->m_Vertices = xr_alloc<Fvector>(MESH->m_VertCount); int id = Ilr->polygon.count/50; if (id==0) id = 1; for (int i=0; i<Ilr->point.count; ++i) { st_lwPoint& Ipt = Ilr->point.pt[i]; Fvector& Mpt = MESH->m_Vertices[i]; Mpt.set (Ipt.pos); } } if (!bResult) break; // polygons MESH->m_FaceCount = Ilr->polygon.count; MESH->m_Faces = xr_alloc<st_Face>(MESH->m_FaceCount); MESH->m_SmoothGroups = xr_alloc<u32>(MESH->m_FaceCount); Memory.mem_fill32 (MESH->m_SmoothGroups,u32(-1),MESH->m_FaceCount); MESH->m_VMRefs.reserve (Ilr->polygon.count*3); IntVec surf_ids; surf_ids.resize(Ilr->polygon.count); int id = Ilr->polygon.count/50; if (id==0) id = 1; for (int i=0; i<Ilr->polygon.count; ++i) { st_Face& Mpol=MESH->m_Faces[i]; st_lwPolygon& Ipol=Ilr->polygon.pol[i]; if (Ipol.nverts!=3) { ELog.DlgMsg(mtError, "Import LWO: Face must contain only 3 vertices!"); bResult=false; break; } for (int pv_i=0; pv_i<3; ++pv_i) { st_lwPolVert& Ipv=Ipol.v[pv_i]; st_FaceVert& Mpv=Mpol.pv[pv_i]; Mpv.pindex =Ipv.index; MESH->m_VMRefs.push_back(st_VMapPtLst()); st_VMapPtLst& m_vm_lst = MESH->m_VMRefs.back(); DEFINE_VECTOR (st_VMapPt,VMapPtVec,VMapPtIt); VMapPtVec vm_lst; Mpv.vmref = MESH->m_VMRefs.size()-1; // parse uv-map int vmpl_cnt =Ipv.nvmaps; st_lwPoint& Ipt =Ilr->point.pt[Mpv.pindex]; int vmpt_cnt =Ipt.nvmaps; if (!vmpl_cnt&&!vmpt_cnt){ ELog.DlgMsg (mtError,"Found mesh without UV's!",0); bResult = false; break; } AStringVec names; if (vmpl_cnt){ // берем из poly for (int vm_i=0; vm_i<vmpl_cnt; vm_i++){ if (Ipv.vm[vm_i].vmap->type!=ID_TXUV) continue; vm_lst.push_back(st_VMapPt()); st_VMapPt& pt = vm_lst.back(); pt.vmap_index = VMIndices[Ipv.vm[vm_i].vmap];// номер моей VMap names.push_back (Ipv.vm[vm_i].vmap->name); pt.index = Ipv.vm[vm_i].index; } } if (vmpt_cnt){ // берем из points for (int vm_i=0; vm_i<vmpt_cnt; vm_i++){ if (Ipt.vm[vm_i].vmap->type!=ID_TXUV) continue; if (std::find(names.begin(),names.end(),Ipt.vm[vm_i].vmap->name)!=names.end()) continue; vm_lst.push_back(st_VMapPt()); st_VMapPt& pt = vm_lst.back(); pt.vmap_index = VMIndices[Ipt.vm[vm_i].vmap]; // номер моей VMap pt.index = Ipt.vm[vm_i].index; } } std::sort(vm_lst.begin(),vm_lst.end(),CompareFunc); // parse weight-map int vm_cnt =Ipt.nvmaps; for (int vm_i=0; vm_i<vm_cnt; vm_i++){ if (Ipt.vm[vm_i].vmap->type!=ID_WGHT) continue; vm_lst.push_back(st_VMapPt()); st_VMapPt& pt = vm_lst.back(); pt.vmap_index = VMIndices[Ipt.vm[vm_i].vmap]; // номер моей VMap pt.index = Ipt.vm[vm_i].index; } m_vm_lst.count = vm_lst.size(); m_vm_lst.pts = xr_alloc<st_VMapPt>(m_vm_lst.count); Memory.mem_copy (m_vm_lst.pts,&*vm_lst.begin(),m_vm_lst.count*sizeof(st_VMapPt)); } if (!bResult) break; // Ipol.surf->alpha_mode - заполнено как номер моего surface surf_ids[i] = Ipol.surf->alpha_mode; } if (!bResult) break; for (u32 pl_id=0; pl_id<MESH->GetFCount(); pl_id++) MESH->m_SurfFaces[m_Surfaces[surf_ids[pl_id]]].push_back(pl_id); if (!bResult) break; k++; //MESH->DumpAdjacency(); if (bNeedOptimize) MESH->OptimizeMesh(false); //MESH->DumpAdjacency(); MESH->RebuildVMaps(); // !!!!!! } } } #ifdef _EDITOR LWO_CloseFile(I); #else lwFreeObject(I); #endif // UI->ProgressEnd(); // UI->SetStatus(""); if (bResult) VerifyMeshNames(); else ELog.DlgMsg(mtError,"Can't parse LWO object."); if (bResult) m_LoadName = (strext(fname))? strcpy(strext(fname),".object"):strcat(strext(fname),".object"); return bResult; }else ELog.DlgMsg(mtError,"Can't import LWO object file."); // UI->ProgressEnd(); // UI->SetStatus(""); return false; }
bool CEditableMesh::LoadMesh(IReader& F){ u32 version=0; R_ASSERT(F.r_chunk(EMESH_CHUNK_VERSION,&version)); if (version!=EMESH_CURRENT_VERSION){ ELog.DlgMsg( mtError, "CEditableMesh: unsuported file version. Mesh can't load."); return false; } R_ASSERT(F.find_chunk(EMESH_CHUNK_MESHNAME)); F.r_stringZ (m_Name); R_ASSERT(F.r_chunk(EMESH_CHUNK_BBOX,&m_Box)); R_ASSERT(F.r_chunk(EMESH_CHUNK_FLAGS,&m_Flags)); F.r_chunk(EMESH_CHUNK_BOP,&m_Ops); R_ASSERT(F.find_chunk(EMESH_CHUNK_VERTS)); m_VertCount = F.r_u32(); if (m_VertCount<3){ Log ("!CEditableMesh: Vertices<3."); return false; } m_Verts = xr_alloc<Fvector>(m_VertCount); F.r (m_Verts, m_VertCount*sizeof(Fvector)); R_ASSERT(F.find_chunk(EMESH_CHUNK_FACES)); m_FaceCount = F.r_u32(); m_Faces = xr_alloc<st_Face>(m_FaceCount); if (m_FaceCount==0){ Log ("!CEditableMesh: Faces==0."); return false; } F.r (m_Faces, m_FaceCount*sizeof(st_Face)); m_SGs = xr_alloc<u32>(m_FaceCount); Memory.mem_fill32 (m_SGs,m_Flags.is(flSGMask)?0:u32(-1),m_FaceCount); u32 sg_chunk_size = F.find_chunk(EMESH_CHUNK_SG); if (sg_chunk_size){ VERIFY (m_FaceCount*sizeof(u32)==sg_chunk_size); F.r (m_SGs, m_FaceCount*sizeof(u32)); } R_ASSERT(F.find_chunk(EMESH_CHUNK_VMREFS)); m_VMRefs.resize (F.r_u32()); int sz_vmpt = sizeof(st_VMapPt); for (VMRefsIt r_it=m_VMRefs.begin(); r_it!=m_VMRefs.end(); r_it++){ r_it->count = F.r_u8(); r_it->pts = xr_alloc<st_VMapPt>(r_it->count); F.r (r_it->pts, sz_vmpt*r_it->count); } R_ASSERT(F.find_chunk(EMESH_CHUNK_SFACE)); string128 surf_name; u32 sface_cnt = F.r_u16(); // surface-face count for (u32 sp_i=0; sp_i<sface_cnt; sp_i++){ F.r_stringZ (surf_name,sizeof(surf_name)); int surf_id; CSurface* surf = m_Parent->FindSurfaceByName(surf_name, &surf_id); VERIFY(surf); IntVec& face_lst = m_SurfFaces[surf]; face_lst.resize (F.r_u32()); if (face_lst.empty()){ Log ("!Empty surface found: %s",surf->_Name()); return false; } F.r (&*face_lst.begin(), face_lst.size()*sizeof(int)); std::sort (face_lst.begin(),face_lst.end()); } if(F.find_chunk(EMESH_CHUNK_VMAPS_2)){ m_VMaps.resize (F.r_u32()); for (VMapIt vm_it=m_VMaps.begin(); vm_it!=m_VMaps.end(); vm_it++){ *vm_it = xr_new<st_VMap>(); F.r_stringZ ((*vm_it)->name); (*vm_it)->dim = F.r_u8(); (*vm_it)->polymap=F.r_u8(); (*vm_it)->type = F.r_u8(); (*vm_it)->resize(F.r_u32()); F.r ((*vm_it)->getVMdata(), (*vm_it)->VMdatasize()); F.r ((*vm_it)->getVIdata(), (*vm_it)->VIdatasize()); if ((*vm_it)->polymap) F.r ((*vm_it)->getPIdata(), (*vm_it)->PIdatasize()); } }else{ if(F.find_chunk(EMESH_CHUNK_VMAPS_1)){ m_VMaps.resize (F.r_u32()); for (VMapIt vm_it=m_VMaps.begin(); vm_it!=m_VMaps.end(); vm_it++){ *vm_it = xr_new<st_VMap>(); F.r_stringZ ((*vm_it)->name); (*vm_it)->dim = F.r_u8(); (*vm_it)->type = F.r_u8(); (*vm_it)->resize(F.r_u32()); F.r ((*vm_it)->getVMdata(), (*vm_it)->VMdatasize() ); } }else{ R_ASSERT(F.find_chunk(EMESH_CHUNK_VMAPS_0)); m_VMaps.resize (F.r_u32()); for (VMapIt vm_it=m_VMaps.begin(); vm_it!=m_VMaps.end(); vm_it++){ *vm_it = xr_new<st_VMap>(); F.r_stringZ ((*vm_it)->name); (*vm_it)->dim = 2; (*vm_it)->type = vmtUV; (*vm_it)->resize(F.r_u32()); F.r ((*vm_it)->getVMdata(), (*vm_it)->VMdatasize() ); } } // update vmaps RebuildVMaps(); } #ifdef _EDITOR if (!EPrefs->object_flags.is(epoDeffLoadRB)){ GenerateFNormals (); GenerateAdjacency (); GenerateVNormals (); GenerateRenderBuffers(); UnloadFNormals (); UnloadAdjacency (); UnloadVNormals (); } if (!EPrefs->object_flags.is(epoDeffLoadCF)) GenerateCFModel(); #endif Optimize(false); RebuildVMaps(); return true; }
//---------------------------------------------------- IC bool build_mesh(const Fmatrix& parent, CEditableMesh* mesh, CGeomPartExtractor* extractor, u32 game_mtl_mask, BOOL ignore_shader) { bool bResult = true; mesh->GenerateVNormals (&parent); // fill faces for (SurfFaces::const_iterator sp_it=mesh->GetSurfFaces().begin(); sp_it!=mesh->GetSurfFaces().end(); sp_it++){ const IntVec& face_lst = sp_it->second; CSurface* surf = sp_it->first; int gm_id = surf->_GameMtl(); if (gm_id==GAMEMTL_NONE_ID){ ELog.DlgMsg (mtError,"Object '%s', surface '%s' contain invalid game material.",mesh->Parent()->m_LibName.c_str(),surf->_Name()); bResult = FALSE; break; } SGameMtl* M = GMLib.GetMaterialByID(gm_id); if (0==M){ ELog.DlgMsg (mtError,"Object '%s', surface '%s' contain undefined game material.",mesh->Parent()->m_LibName.c_str(),surf->_Name()); bResult = FALSE; break; } if (!M->Flags.is(game_mtl_mask)) continue; // check engine shader compatibility if (!ignore_shader){ IBlender* B = EDevice.Resources->_FindBlender(surf->_ShaderName()); if (FALSE==B){ ELog.Msg (mtError,"Can't find engine shader '%s'. Object '%s', surface '%s'. Export interrupted.",surf->_ShaderName(),mesh->Parent()->m_LibName.c_str(),surf->_Name()); bResult = FALSE; break; } if (TRUE==B->canBeLMAPped()){ ELog.Msg (mtError,"Object '%s', surface '%s' contain static engine shader - '%s'. Export interrupted.",mesh->Parent()->m_LibName.c_str(),surf->_Name(),surf->_ShaderName()); bResult = FALSE; break; } } const st_Face* faces = mesh->GetFaces(); VERIFY(faces); const Fvector* vn = mesh->GetVNormals(); VERIFY(vn); const Fvector* pts = mesh->GetVertices(); VERIFY(pts); for (IntVec::const_iterator f_it=face_lst.begin(); f_it!=face_lst.end(); f_it++){ const st_Face& face = faces[*f_it]; Fvector v[3],n[3]; parent.transform_tiny (v[0],pts[face.pv[0].pindex]); parent.transform_tiny (v[1],pts[face.pv[1].pindex]); parent.transform_tiny (v[2],pts[face.pv[2].pindex]); parent.transform_dir (n[0],vn[*f_it*3+0]); n[0].normalize(); parent.transform_dir (n[1],vn[*f_it*3+1]); n[1].normalize(); parent.transform_dir (n[2],vn[*f_it*3+2]); n[2].normalize(); const Fvector2* uv[3]; mesh->GetFaceTC (*f_it,uv); extractor->AppendFace (surf,v,n,uv); } if (!bResult) break; } mesh->UnloadVNormals (); return bResult; }
bool SceneBuilder::BuildSOMModel() { BOOL bResult = TRUE; CMemoryWriter F; F.open_chunk (0); F.w_u32 (0); F.close_chunk (); F.open_chunk (1); ObjectList& lst = Scene->ListObj(OBJCLASS_SCENEOBJECT); for (ObjectIt it=lst.begin(); it!=lst.end(); it++){ CSceneObject* S = (CSceneObject*)(*it); CEditableObject* E = S->GetReference(); R_ASSERT(E); if (E->m_Flags.is(CEditableObject::eoSoundOccluder)){ Fvector v; const Fmatrix& parent = S->_Transform(); for (EditMeshIt m_it=E->FirstMesh(); m_it!=E->LastMesh(); m_it++){ for (SurfFacesPairIt sf_it=(*m_it)->m_SurfFaces.begin(); sf_it!=(*m_it)->m_SurfFaces.end(); sf_it++){ CSurface* surf = sf_it->first; int gm_id = surf->_GameMtl(); if (gm_id==GAMEMTL_NONE_ID){ ELog.DlgMsg (mtError,"Object '%s', surface '%s' contain invalid game material.",(*m_it)->Parent()->m_LibName.c_str(),surf->_Name()); bResult = FALSE; break; } SGameMtl* mtl = GMLib.GetMaterialByID(gm_id); if (0==mtl){ ELog.DlgMsg (mtError,"Object '%s', surface '%s' contain undefined game material.",(*m_it)->Parent()->m_LibName.c_str(),surf->_Name()); bResult = FALSE; break; } BOOL b2Sided = surf->m_Flags.is(CSurface::sf2Sided); IntVec& i_lst = sf_it->second; for (IntIt i_it=i_lst.begin(); i_it!=i_lst.end(); i_it++){ st_Face& face = (*m_it)->m_Faces[*i_it]; for (int k=0; k<3; k++){ parent.transform_tiny(v,(*m_it)->m_Verts[face.pv[k].pindex]); F.w_fvector3(v); } F.w_u32 (b2Sided); F.w_float (mtl->fSndOcclusionFactor); } } } } } BOOL bValid = !!F.chunk_size()&&bResult; F.close_chunk(); if (bValid){ xr_string som_name = MakeLevelPath("level.som"); bValid = F.save_to(som_name.c_str()); } return bValid; }