@@ -17,14 +17,297 @@ extern "C" {
1717#ifdef _EDITOR
1818 #include " ResourceManager.h"
1919
20- extern " C" __declspec(dllimport) lwObject* LWO_ImportObject (char * filename, lwObject *new_obj );
21- extern " C" __declspec(dllimport) void LWO_CloseFile (lwObject *new_obj );
20+ extern " C" __declspec(dllimport) lwObject* LWOImportObject (char * filename);
21+ extern " C" __declspec(dllimport) void LWOCloseFile (lwObject* object );
2222#endif
2323
24- DEFINE_MAP (void *,int ,VMIndexLink,VMIndexLinkIt);
25-
26- bool CompareFunc (const st_VMapPt& vm0, const st_VMapPt& vm1){
27- return vm0.vmap_index <vm1.vmap_index ;
28- };
29-
30-
24+ #ifdef _LW_EXPORT
25+ bool CEditableObject::ImportLWO (const char * fn, bool optimize)
26+ {
27+ string512 fname;
28+ strcpy (fname, fn);
29+ #ifdef _EDITOR
30+ lwObject* lwObj = LWOImportObject (fname);
31+ #else
32+ u32 errId;
33+ int errPos;
34+ lwObject* lwObj = lwGetObject (fname, &errId, &errPos);
35+ #endif
36+ if (!lwObj)
37+ {
38+ ELog.DlgMsg (mtError, " Can't import LWO object file!" );
39+ return false ;
40+ }
41+ ELog.Msg (mtInformation, " CEditableObject: import lwo %s..." , fname);
42+ bool result = false ; // assume fail
43+ // parse lwo object
44+ m_Meshes.reserve (lwObj->nlayers );
45+ m_Surfaces.reserve (lwObj->nsurfs );
46+ int surfaceId = 0 ;
47+ for (lwSurface* lwSurf = lwObj->surf ; lwSurf; lwSurf = lwSurf->next )
48+ {
49+ lwSurf->alpha_mode = surfaceId; // save surface id for internal use
50+ auto surf = new CSurface ();
51+ m_Surfaces.push_back (surf);
52+ surf->SetName (lwSurf->name && lwSurf->name [0 ] ? lwSurf->name : " Default" );
53+ surf->m_Flags .set (CSurface::sf2Sided, lwSurf->sideflags == 3 );
54+ AnsiString enName = " default" , lcName = " default" , gmName = " default" ;
55+ if (lwSurf->nshaders && !stricmp (lwSurf->shader ->name , SH_PLUGIN_NAME))
56+ {
57+ auto shader = (XRShader*)lwSurf->shader ->data ;
58+ enName = shader->en_name ;
59+ lcName = shader->lc_name ;
60+ gmName = shader->gm_name ;
61+ }
62+ else
63+ ELog.Msg (mtError, " CEditableObject: Shader not found on surface '%s'." , surf->_Name ());
64+ #ifdef _EDITOR
65+ if (!Device.Resources ->_FindBlender (enName.c_str ()))
66+ {
67+ ELog.Msg (mtError, " CEditableObject: Render shader '%s' - can't find in library.\n "
68+ " Using 'default' shader on surface '%s'." , enName.c_str (), surf->_Name ());
69+ enName = " default" ;
70+ }
71+ if (!Device.ShaderXRLC .Get (lcName.c_str ()))
72+ {
73+ ELog.Msg (mtError, " CEditableObject: Compiler shader '%s' - can't find in library.\n "
74+ " Using 'default' shader on surface '%s'." , lcName.c_str (), surf->_Name ());
75+ lcName = " default" ;
76+ }
77+ if (!GMLib.GetMaterial (gmName.c_str ()))
78+ {
79+ ELog.Msg (mtError, " CEditableObject: Game material '%s' - can't find in library.\n "
80+ " Using 'default' material on surface '%s'." , lcName.c_str (), surf->_Name ());
81+ gmName = " default" ;
82+ }
83+ #endif
84+ // fill texture layers
85+ u32 textureCount = 0 ;
86+ for (st_lwTexture* Itx = lwSurf->color .tex ; Itx; Itx = Itx->next )
87+ {
88+ string1024 tname = " " ;
89+ textureCount++;
90+ int cidx = -1 ;
91+ if (Itx->type == ID_IMAP)
92+ cidx = Itx->param .imap .cindex ;
93+ else
94+ {
95+ ELog.DlgMsg (mtError, " Import LWO (Surface '%s'): 'Texture' is not Image Map!" , surf->_Name ());
96+ goto importFailed;
97+ }
98+ if (cidx != -1 )
99+ {
100+ // get textures
101+ for (st_lwClip* lwClip = lwObj->clip ; lwClip; lwClip = lwClip->next )
102+ {
103+ if (cidx == lwClip->index && lwClip->type == ID_STIL)
104+ {
105+ strcpy (tname, lwClip->source .still .name );
106+ break ;
107+ }
108+ }
109+ if (tname[0 ] == 0 )
110+ {
111+ ELog.DlgMsg (mtError, " Import LWO (Surface '%s'): "
112+ " 'Texture' name is empty or non 'STIL' type!" , surf->_Name ());
113+ goto importFailed;
114+ }
115+ string256 textureName;
116+ _splitpath (tname, nullptr , nullptr , textureName, nullptr );
117+ surf->SetTexture (EFS.AppendFolderToName (textureName, 256 , 1 , true ));
118+ // get vmap refs
119+ surf->SetVMap (Itx->param .imap .vmap_name );
120+ }
121+ }
122+ if (!surf->_VMap () || *surf->_VMap () == 0 )
123+ {
124+ ELog.DlgMsg (mtError, " Invalid surface '%s'. Empty VMap." , surf->_Name ());
125+ goto importFailed;
126+ }
127+ if (!surf->_Texture () || *surf->_Texture () == 0 )
128+ {
129+ ELog.DlgMsg (mtError, " Can't create shader. Invalid surface '%s'. Textures empty." , surf->_Name ());
130+ goto importFailed;
131+ }
132+ if (enName.c_str () == 0 )
133+ {
134+ ELog.DlgMsg (mtError, " Can't create shader. Invalid surface '%s'. Shader empty." , surf->_Name ());
135+ goto importFailed;
136+ }
137+ surf->SetShader (enName.c_str ());
138+ surf->SetShaderXRLC (lcName.c_str ());
139+ surf->SetGameMtl (gmName.c_str ());
140+ surf->SetFVF (D3DFVF_XYZ | D3DFVF_NORMAL | textureCount << D3DFVF_TEXCOUNT_SHIFT);
141+ surfaceId++;
142+ }
143+ // process mesh layers
144+ for (st_lwLayer* lwLayer = lwObj->layer ; lwLayer; lwLayer = lwLayer->next )
145+ {
146+ auto mesh = new CEditableMesh (this );
147+ m_Meshes.push_back (mesh);
148+ mesh->SetName (lwLayer->name ? lwLayer->name : " " );
149+ auto bbox = lwLayer->bbox ;
150+ mesh->m_Box .set (bbox[0 ], bbox[1 ], bbox[2 ], bbox[3 ], bbox[4 ], bbox[5 ]);
151+ // parse mesh(lwo-layer) data
152+ if (lwLayer->nvmaps == 0 )
153+ {
154+ ELog.DlgMsg (mtError, " Import LWO: Mesh layer must contain UV map!" );
155+ goto importFailed;
156+ }
157+ // XXX nitrocaster: incompatible with multithreaded import
158+ static xr_map<void *, int > vmIndices;
159+ vmIndices.clear ();
160+ int vmIndex = 0 ;
161+ for (st_lwVMap* lwVmap = lwLayer->vmap ; lwVmap; lwVmap = lwVmap->next )
162+ {
163+ switch (lwVmap->type )
164+ {
165+ case ID_TXUV:
166+ {
167+ if (lwVmap->dim != 2 )
168+ {
169+ ELog.DlgMsg (mtError, " Import LWO: 'UV Map' must be equal to 2!" );
170+ goto importFailed;
171+ }
172+ mesh->m_VMaps .push_back (new st_VMap (lwVmap->name , vmtUV, !!lwVmap->perpoly ));
173+ st_VMap* vmap = mesh->m_VMaps .back ();
174+ vmap->copyfrom (*lwVmap->val , lwVmap->nverts );
175+ // flip uv
176+ for (int uvIndex = 0 ; uvIndex < vmap->size (); uvIndex++)
177+ {
178+ Fvector2& uv = vmap->getUV (uvIndex);
179+ uv.y = 1 .f - uv.y ;
180+ }
181+ vmIndices[lwVmap] = vmIndex++;
182+ break ;
183+ }
184+ case ID_WGHT:
185+ {
186+ if (lwVmap->dim != 1 )
187+ {
188+ ELog.DlgMsg (mtError, " Import LWO: 'Weight' must be equal to 1!" );
189+ goto importFailed;
190+ }
191+ mesh->m_VMaps .push_back (new st_VMap (lwVmap->name , vmtWeight, false ));
192+ st_VMap* vmap = mesh->m_VMaps .back ();
193+ vmap->copyfrom (*lwVmap->val , lwVmap->nverts );
194+ vmIndices[lwVmap] = vmIndex++;
195+ break ;
196+ }
197+ case ID_PICK: ELog.Msg (mtError, " Found 'PICK' VMAP. Import failed." ); goto importFailed;
198+ case ID_MNVW: ELog.Msg (mtError, " Found 'MNVW' VMAP. Import failed." ); goto importFailed;
199+ case ID_MORF: ELog.Msg (mtError, " Found 'MORF' VMAP. Import failed." ); goto importFailed;
200+ case ID_SPOT: ELog.Msg (mtError, " Found 'SPOT' VMAP. Import failed." ); goto importFailed;
201+ case ID_RGB: ELog.Msg (mtError, " Found 'RGB' VMAP. Import failed." ); goto importFailed;
202+ case ID_RGBA: ELog.Msg (mtError, " Found 'RGBA' VMAP. Import failed." ); goto importFailed;
203+ }
204+ }
205+ // points
206+ mesh->m_VertCount = lwLayer->point .count ;
207+ mesh->m_Vertices = xr_alloc<Fvector>(mesh->m_VertCount );
208+ for (int i = 0 ; i < lwLayer->point .count ; i++)
209+ {
210+ st_lwPoint& lwPoint = lwLayer->point .pt [i];
211+ Fvector& vertex = mesh->m_Vertices [i];
212+ vertex.set (lwPoint.pos );
213+ }
214+ // polygons
215+ mesh->m_FaceCount = lwLayer->polygon .count ;
216+ mesh->m_Faces = xr_alloc<st_Face>(mesh->m_FaceCount );
217+ mesh->m_SmoothGroups = xr_alloc<u32 >(mesh->m_FaceCount );
218+ memset (mesh->m_SmoothGroups , u32 (-1 ), mesh->m_FaceCount );
219+ mesh->m_VMRefs .reserve (lwLayer->polygon .count *3 );
220+ xr_vector<int > surfIds (lwLayer->polygon .count );
221+ for (int i = 0 ; i < lwLayer->polygon .count ; i++)
222+ {
223+ st_Face& face = mesh->m_Faces [i];
224+ st_lwPolygon& lwPoly = lwLayer->polygon .pol [i];
225+ if (lwPoly.nverts != 3 )
226+ {
227+ ELog.DlgMsg (mtError, " Import LWO: Face must contain only 3 vertices!" );
228+ goto importFailed;
229+ }
230+ for (int fvIndex = 0 ; fvIndex < 3 ; fvIndex++)
231+ {
232+ st_lwPolVert& lwFaceVert = lwPoly.v [fvIndex];
233+ st_FaceVert& faceVert = face.pv [fvIndex];
234+ faceVert.pindex = lwFaceVert.index ;
235+ mesh->m_VMRefs .push_back (st_VMapPtLst ());
236+ st_VMapPtLst& vmPointList = mesh->m_VMRefs .back ();
237+ faceVert.vmref = mesh->m_VMRefs .size ()-1 ;
238+ // parse uv-map
239+ st_lwPoint& lwPoint = lwLayer->point .pt [faceVert.pindex ];
240+ if (lwFaceVert.nvmaps == 0 && lwPoint.nvmaps == 0 )
241+ {
242+ ELog.DlgMsg (mtError, " Found mesh without UV's!" );
243+ goto importFailed;
244+ }
245+ xr_vector<st_VMapPt> vmPoints;
246+ AStringVec names;
247+ // process polys
248+ for (int j = 0 ; j < lwFaceVert.nvmaps ; j++)
249+ {
250+ if (lwFaceVert.vm [j].vmap ->type != ID_TXUV)
251+ continue ;
252+ vmPoints.push_back (st_VMapPt ());
253+ st_VMapPt& pt = vmPoints.back ();
254+ pt.vmap_index = vmIndices[lwFaceVert.vm [j].vmap ]; // VMap id
255+ names.push_back (lwFaceVert.vm [j].vmap ->name );
256+ pt.index = lwFaceVert.vm [j].index ;
257+ }
258+ // process points
259+ for (int j = 0 ; j < lwPoint.nvmaps ; j++)
260+ {
261+ if (lwPoint.vm [j].vmap ->type != ID_TXUV)
262+ continue ;
263+ if (std::find (names.begin (), names.end (), lwPoint.vm [j].vmap ->name ) != names.end ())
264+ continue ;
265+ vmPoints.push_back (st_VMapPt ());
266+ st_VMapPt& pt = vmPoints.back ();
267+ pt.vmap_index = vmIndices[lwPoint.vm [j].vmap ]; // VMap id
268+ pt.index = lwPoint.vm [j].index ;
269+ }
270+ auto cmpFunc = [](const st_VMapPt& a, const st_VMapPt& b)
271+ { return a.vmap_index < b.vmap_index ; };
272+ std::sort (vmPoints.begin (), vmPoints.end (), cmpFunc);
273+ // parse weight-map
274+ for (int j = 0 ; j < lwPoint.nvmaps ; j++)
275+ {
276+ if (lwPoint.vm [j].vmap ->type != ID_WGHT)
277+ continue ;
278+ vmPoints.push_back (st_VMapPt ());
279+ st_VMapPt& pt = vmPoints.back ();
280+ pt.vmap_index = vmIndices[lwPoint.vm [j].vmap ]; // VMap id
281+ pt.index = lwPoint.vm [j].index ;
282+ }
283+ vmPointList.count = vmPoints.size ();
284+ vmPointList.pts = xr_alloc<st_VMapPt>(vmPointList.count );
285+ memcpy (vmPointList.pts , &*vmPoints.begin (), vmPointList.count *sizeof (st_VMapPt));
286+ }
287+ // lwPoly.surf->alpha_mode stores reviously saved surface id
288+ surfIds[i] = lwPoly.surf ->alpha_mode ;
289+ }
290+ for (u32 polyId = 0 ; polyId < mesh->GetFCount (); polyId++)
291+ mesh->m_SurfFaces [m_Surfaces[surfIds[polyId]]].push_back (polyId);
292+ if (optimize)
293+ mesh->OptimizeMesh (false );
294+ mesh->RebuildVMaps ();
295+ }
296+ result = true ;
297+ importFailed:
298+ #ifdef _EDITOR
299+ LWOCloseFile (lwObj);
300+ #else
301+ lwFreeObject (lwObj);
302+ #endif
303+ if (result)
304+ {
305+ VerifyMeshNames ();
306+ char * ext = strext (fname);
307+ m_LoadName = ext ? strcpy (ext, " .object" ) : strcat (fname, " .object" );
308+ }
309+ else
310+ ELog.DlgMsg (mtError, " Can't parse LWO object." );
311+ return result;
312+ }
313+ #endif
0 commit comments