@@ -17,14 +17,297 @@ extern "C" {
17
17
#ifdef _EDITOR
18
18
#include " ResourceManager.h"
19
19
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 );
22
22
#endif
23
23
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