1 #include "xr_mesh_builder.h"
2 #include "xr_object.h"
3 #include "xr_utils.h"
4 #include "xr_mesh_utils.h"
5
6 using namespace xray_re;
7
set(uint32_t signature,uint32_t x0,uint32_t x1,uint32_t x2)8 xr_mesh_builder::b_face& xr_mesh_builder::b_face::set(uint32_t signature, uint32_t x0, uint32_t x1, uint32_t x2)
9 {
10 xr_assert(signature);
11 if (signature & xr_vbuf::S_POINTS) {
12 v0 = x0;
13 v1 = x1;
14 v2 = x2;
15 }
16 if (signature & xr_vbuf::S_NORMALS) {
17 n0 = x0;
18 n1 = x1;
19 n2 = x2;
20 }
21 if (signature & xr_vbuf::S_TEXCOORDS) {
22 tc0 = x0;
23 tc1 = x1;
24 tc2 = x2;
25 }
26 return *this;
27 }
28
is_duplicate(const b_face & face) const29 bool xr_mesh_builder::b_face::is_duplicate(const b_face& face) const
30 {
31 for (uint_fast32_t i0 = 0; i0 != 3; ++i0) {
32 if (v[i0] != face.v0)
33 continue;
34 uint_fast32_t i1 = (1 << i0) & 3;
35 uint_fast32_t i2 = (1 << i1) & 3;
36 return v[i1] == face.v1 && v[i2] == face.v2 &&
37 sector == face.sector && surface == face.surface &&
38 n[i0] == face.n0 && n[i1] == face.n1 && n[i2] == face.n2 &&
39 tc[i0] == face.tc0 && tc[i1] == face.tc1 && tc[i2] == face.tc2;
40 }
41 return false;
42 }
43
is_back(const b_face & face,const std::vector<fvector3> & normals,float normal_tolerance) const44 bool xr_mesh_builder::b_face::is_back(const b_face& face,
45 const std::vector<fvector3>& normals, float normal_tolerance) const
46 {
47 for (uint_fast32_t i0 = 0; i0 != 3; ++i0) {
48 if (v[i0] != face.v0)
49 continue;
50 uint_fast32_t i1 = (1 << i0) & 3;
51 uint_fast32_t i2 = (1 << i1) & 3;
52 return v[i1] == face.v2 && v[i2] == face.v1 &&
53 sector == face.sector && surface == face.surface &&
54 tc[i0] == face.tc0 && tc[i1] == face.tc2 && tc[i2] == face.tc1 &&
55 normals[n[i0]].inverted(normals[face.n0], normal_tolerance) &&
56 normals[n[i1]].inverted(normals[face.n2], normal_tolerance) &&
57 normals[n[i2]].inverted(normals[face.n1], normal_tolerance);
58 }
59 return false;
60 }
61
is_same_layer(uint_fast32_t v0,uint_fast32_t v1) const62 bool xr_mesh_builder::b_face::is_same_layer(uint_fast32_t v0, uint_fast32_t v1) const
63 {
64 return ((1u << local_vert_idx(v0)) & 3) != local_vert_idx(v1);
65 }
66
is_edge_smooth(const b_face & face,uint_fast32_t v0,uint_fast32_t v1) const67 bool xr_mesh_builder::b_face::is_edge_smooth(const b_face& face, uint_fast32_t v0, uint_fast32_t v1) const
68 {
69 uint_fast32_t i0 = local_vert_idx(v0);
70 uint_fast32_t i1 = local_vert_idx(v1);
71 uint_fast32_t j0 = face.local_vert_idx(v0);
72 uint_fast32_t j1 = face.local_vert_idx(v1);
73 return n[i0] == face.n[j0] && n[i1] == face.n[j1] &&
74 v[3 - i0 - i1] != face.v[3 - j0 - j1];
75 }
76
77 ////////////////////////////////////////////////////////////////////////////////
78
xr_mesh_builder()79 xr_mesh_builder::xr_mesh_builder() {}
80
~xr_mesh_builder()81 xr_mesh_builder::~xr_mesh_builder() {}
82
set_tc_fix(bool tc_fix)83 void xr_mesh_builder::set_tc_fix(bool tc_fix) { m_vb.set_tc_fix(tc_fix); }
84
85 template<typename T> struct xr_mesh_builder::b_proxy::less {
86 const T* data;
lessxr_mesh_builder::b_proxy::less87 explicit less(const T* _data): data(_data) {}
operator ()xr_mesh_builder::b_proxy::less88 inline bool operator()(const b_proxy& l, const b_proxy& r) const {
89 return data[l.index] < data[r.index];
90 }
91 };
92
93 template<typename T1, typename T2> struct xr_mesh_builder::b_proxy::less2 {
94 const T1* data1;
95 const T2* data2;
less2xr_mesh_builder::b_proxy::less296 explicit less2(const T1* _data1, const T2* _data2): data1(_data1), data2(_data2) {}
operator ()xr_mesh_builder::b_proxy::less297 inline bool operator()(const b_proxy& l, const b_proxy& r) const {
98 return data1[l.index] < data1[r.index] ||
99 (data1[l.index] == data1[r.index] && data2[l.index] < data2[r.index]);
100 }
101 };
102
prepare(uint32_t signature,size_t num_vertices,size_t num_indices)103 void xr_mesh_builder::prepare(uint32_t signature, size_t num_vertices, size_t num_indices)
104 {
105 m_vb.set_signature(signature);
106 m_vb.reserve(num_vertices);
107 m_refs.reserve(num_vertices);
108 m_faces.reserve(num_indices/3);
109 }
110
push(const xr_vbuf & vb,const xr_ibuf & ib,uint16_t texture,uint16_t eshader)111 void xr_mesh_builder::push(const xr_vbuf& vb, const xr_ibuf& ib, uint16_t texture, uint16_t eshader)
112 {
113 b_face face_template;
114 face_template.surface.set(texture, eshader);
115 if (vb.has_lightmaps())
116 face_template.surface.flags |= RSF_LIGHTMAP;
117 __push(vb, ib, 0, face_template, PF_DEFAULT);
118 }
119
__push(const xr_vbuf & vb,const xr_ibuf & ib,const fmatrix * xform,const b_face & face_template,unsigned pflags)120 void xr_mesh_builder::__push(const xr_vbuf& vb, const xr_ibuf& ib, const fmatrix* xform,
121 const b_face& face_template, unsigned pflags)
122 {
123 size_t num_new_faces = 0;
124 uint32_t signature = m_vb.signature(), vb_offset = uint32_t(m_vb.size() & UINT32_MAX);
125 b_face face(face_template);
126 for (size_t i = 0, num_indices = ib.size(); i != num_indices; i += 3) {
127 uint32_t v0 = ib[i + 0];
128 uint32_t v1 = ib[i + 1];
129 const fvector3& p0 = vb.p(v0);
130 const fvector3& p1 = vb.p(v1);
131 if (p0 == p1)
132 continue;
133 uint32_t v2 = ib[i + 2];
134 const fvector3& p2 = vb.p(v2);
135 if (p1 == p2 || p2 == p0)
136 continue;
137
138 float area = calc_area(p0, p1, p2);
139 if (area <= 1e-5f) {
140 m_build_err.zero_area_face(p0, p1, p2);
141 if (pflags & PF_REMOVE_ZERO_FACE)
142 continue;
143 }
144 float perim = calc_perimeter(vb.tc(v0), vb.tc(v1), vb.tc(v2));
145 if (perim <= 1/8192.f) {
146 m_build_err.zero_uv_area_face(p0, p1, p2);
147 if (pflags & PF_REMOVE_ZERO_UV_FACE)
148 continue;
149 }
150 #if 0
151 if (vb.has_lightmaps()) {
152 const fvector2& lm0 = vb.lm(v0);
153 const fvector2& lm1 = vb.lm(v1);
154 const fvector2& lm2 = vb.lm(v2);
155 #if 1
156 fvector3 uv0, uv1, uv2;
157 uv0.set(lm0.x, 0, lm0.y);
158 uv1.set(lm1.x, 0, lm1.y);
159 uv2.set(lm2.x, 0, lm2.y);
160 float k = calc_area_xz(uv0, uv1, uv2)*1024.f*1024.f/calc_area(p0, p1, p2);
161 printf("lm_density: %f\n", k);
162 #else
163 float k01 = lm0.distance(lm1)*1024.f/p0.distance(p1);
164 float k12 = lm1.distance(lm2)*1024.f/p1.distance(p2);
165 float k20 = lm2.distance(lm0)*1024.f/p2.distance(p0);
166 // if (equivalent(k01, 0.f)) {
167 if (equivalent(k01, 5.f)) {
168 // if (k01 < 2.f) {
169 printf(" face: [%f,%f,%f][%f,%f,%f][%f,%f,%f],\n lm: [%f,%f][%f,%f][%f,%f]\n",
170 p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z,
171 lm0.x, lm0.y, lm1.x, lm1.y, lm2.x, lm2.y);
172 }
173 printf("lm_density: %.2f/%.2f/%.2f\n", k01, k12, k20);
174 #endif
175 }
176 #endif
177 m_faces.push_back(face.set(signature, vb_offset + v0, vb_offset + v1, vb_offset + v2));
178 ++num_new_faces;
179 }
180 if (num_new_faces) {
181 for (size_t i = vb.size(); i != 0; --i, ++vb_offset)
182 m_refs.push_back(b_proxy(vb_offset));
183 m_vb.push(vb, &ib, xform);
184 }
185 }
186
187 template<typename T> void
create_unique_array(b_proxy_vec & refs,std::vector<T> & data,const T * raw_data,uint32_t * mapping)188 xr_mesh_builder::create_unique_array(b_proxy_vec& refs, std::vector<T>& data, const T* raw_data, uint32_t* mapping)
189 {
190 std::sort(refs.begin(), refs.end(), b_proxy::less<T>(raw_data));
191 uint32_t index = 0;
192 for (b_proxy_vec_it it = refs.begin(), end = refs.end(); it != end; ++index) {
193 const T& value = raw_data[it->index];
194 data.push_back(value);
195 mapping[it->index] = index;
196 while (++it != end && raw_data[it->index] == value)
197 mapping[it->index] = index;
198 }
199 }
200
201 template<typename T1, typename T2> void
create_unique_array2(b_proxy_vec & refs,std::vector<T1> & data1,std::vector<T2> & data2,const T1 * raw_data1,const T2 * raw_data2,uint32_t * mapping)202 xr_mesh_builder::create_unique_array2(b_proxy_vec& refs, std::vector<T1>& data1, std::vector<T2>& data2,
203 const T1* raw_data1, const T2* raw_data2, uint32_t* mapping)
204 {
205 std::sort(refs.begin(), refs.end(), b_proxy::less2<T1, T2>(raw_data1, raw_data2));
206 uint32_t index = 0;
207 for (b_proxy_vec_it it = refs.begin(), end = refs.end(); it != end; ++index) {
208 const T1& value1 = raw_data1[it->index];
209 data1.push_back(value1);
210 const T2& value2 = raw_data2[it->index];
211 data2.push_back(value2);
212 mapping[it->index] = index;
213 while (++it != end && raw_data1[it->index] == value1 && raw_data2[it->index] == value2)
214 mapping[it->index] = index;
215 }
216 }
217
compact_geometry()218 void xr_mesh_builder::compact_geometry()
219 {
220 uint32_t* mapping = new uint32_t[m_refs.size()];
221 if (m_vb.has_influences())
222 create_unique_array2(m_refs, m_points, m_influences, m_vb.p(), m_vb.w(), mapping);
223 else
224 create_unique_array(m_refs, m_points, m_vb.p(), mapping);
225 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end(); it != end; ++it) {
226 it->v0 = mapping[it->v0];
227 it->v1 = mapping[it->v1];
228 it->v2 = mapping[it->v2];
229 }
230 if (m_vb.has_normals()) {
231 create_unique_array(m_refs, m_normals, m_vb.n(), mapping);
232 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end(); it != end; ++it) {
233 it->n0 = mapping[it->n0];
234 it->n1 = mapping[it->n1];
235 it->n2 = mapping[it->n2];
236 }
237 }
238 if (m_vb.has_texcoords()) {
239 create_unique_array(m_refs, m_texcoords, m_vb.tc(), mapping);
240 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end(); it != end; ++it) {
241 it->tc0 = mapping[it->tc0];
242 it->tc1 = mapping[it->tc1];
243 it->tc2 = mapping[it->tc2];
244 }
245 }
246 delete[] mapping;
247
248 m_vb.clear();
249 b_proxy_vec().swap(m_refs);
250
251 #if 0
252 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end(); it != end; ++it) {
253 fvector3 n1, n2, n3;
254 uint16_t packed1 = n1.calc_normal(m_points[it->v0], m_points[it->v1], m_points[it->v2]).compress();
255 uint16_t packed2 = n2.decompress(packed1).compress();
256 uint16_t packed3 = n3.decompress(packed2).compress();
257 msg("distance12=%f, distance23=%f", n1.distance(n2), n2.distance(n3));
258 xr_assert(n1.distance(n2) < 0.3f);
259 }
260 #endif
261 }
262
operator ()bad_face_pred263 struct bad_face_pred { bool operator()(const xr_mesh_builder::b_face& face) const { return face.surf_idx == BAD_IDX; }};
264
remove_duplicate_faces()265 void xr_mesh_builder::remove_duplicate_faces()
266 {
267 generate_vertex_faces();
268 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end(); it != end; ++it) {
269 for (uint_fast32_t next = m_vertex_faces[it->v0]; next != BAD_IDX;) {
270 b_face* face = &m_faces[next];
271 if (face > &*it && it->is_duplicate(*face)) {
272 it->surf_idx = BAD_IDX;
273 goto skip;
274 }
275 next = face->next_face_idx(it->v0);
276 }
277 skip:;
278 }
279 m_faces.erase(std::remove_if(m_faces.begin(), m_faces.end(), bad_face_pred()), m_faces.end());
280 }
281
282 // FIXME: it should be possible to determine the "right" side in
283 // model (external) OGFs using simple face ordering heuristics.
284 // Not sure for the level (embedded) OGFs though.
remove_back_faces(float normal_tolerance)285 void xr_mesh_builder::remove_back_faces(float normal_tolerance)
286 {
287 generate_vertex_faces();
288
289 size_t num_faces = m_faces.size();
290
291 uint32_t* face_backs = new uint32_t[num_faces];
292 xr_uninitialized_fill_n(face_backs, num_faces, BAD_IDX);
293 uint32_t face_idx = 0;
294 for (b_face_vec_cit it = m_faces.begin(), end = m_faces.end();
295 it != end; ++it, ++face_idx) {
296 for (uint_fast32_t next = m_vertex_faces[it->v0]; next != BAD_IDX;) {
297 b_face& face = m_faces[next];
298 if (it->is_back(face, m_normals, normal_tolerance)) {
299 face_backs[face_idx] = uint32_t(next & UINT32_MAX);
300 face_backs[next] = face_idx;
301 break;
302 }
303 next = face.next_face_idx(it->v0);
304 }
305 }
306
307 create_edges();
308
309 std::vector<uint32_t> adjacents;
310 adjacents.reserve(512);
311 std::vector<int> sides;
312 sides.reserve(256);
313
314 uint32_t* lgroups = new uint32_t[num_faces];
315 xr_uninitialized_fill_n(lgroups, num_faces, BAD_IDX);
316
317 uint32_t lgroup = 0;
318 for (size_t k = 0; k != num_faces; ++k) {
319 if (face_backs[k] == BAD_IDX || lgroups[k] != BAD_IDX)
320 continue;
321 int side = 0;
322 face_idx = uint32_t(k & UINT32_MAX);
323 lgroups[face_idx] = lgroup;
324 lgroups[face_backs[face_idx]] = lgroup + 1;
325 for (;;) {
326 const b_face& face = m_faces[face_idx];
327 for (uint_fast32_t i = 3, v0, v1 = face.v0; i != 0; v1 = v0) {
328 b_edge* edge = find_edge(v0 = face.v[--i], v1);
329 xr_assert(edge && (v0 == edge->v1 || v1 == edge->v1));
330 if (edge->size > 4)
331 continue;
332 for (uint_fast32_t next = edge->face0; next != BAD_IDX;) {
333 const b_face& adjacent = m_faces[next];
334 if (next != face_idx && next != face_backs[face_idx] &&
335 lgroups[next] == BAD_IDX) {
336 bool same_layer = adjacent.is_same_layer(v0, v1);
337 uint_fast32_t next_back = face_backs[next];
338 if (next_back == BAD_IDX) {
339 if (edge->size > 3)
340 break;
341 if (same_layer)
342 --side;
343 else
344 ++side;
345 } else if (same_layer) {
346 adjacents.push_back(uint32_t(next & UINT32_MAX));
347 lgroups[next] = lgroup;
348 lgroups[next_back] = lgroup + 1;
349 break;
350 } else {
351 adjacents.push_back(uint32_t(next_back & UINT32_MAX));
352 lgroups[next_back] = lgroup;
353 lgroups[next] = lgroup + 1;
354 break;
355 }
356 }
357
358 // check for endless cycle. It`s in build 2232 l06_rostok
359 uint_fast32_t temp = adjacent.next_face_idx(v0, v1);
360 if (next == temp)
361 break;
362 next = temp;
363 }
364 }
365 if (adjacents.empty())
366 break;
367 face_idx = adjacents.back();
368 adjacents.pop_back();
369
370 }
371 if (side == 0)
372 side = -1;
373 sides.push_back(side);
374 lgroup += 2;
375 }
376
377 face_idx = 0;
378 b_face_vec_it last = m_faces.begin();
379 for (b_face_vec_it it = last, end = m_faces.end(); it != end; ++it, ++face_idx) {
380 if (face_backs[face_idx] != BAD_IDX) {
381 int side = sides[(lgroup = lgroups[face_idx])/2];
382 if (lgroup & 1)
383 side = -side;
384 if (side < 0)
385 it->surface.flags |= RSF_TWO_SIDED;
386 else
387 continue;
388 }
389 if (last != it)
390 *last = *it;
391 ++last;
392 }
393 m_faces.erase(last, m_faces.end());
394
395 delete[] lgroups;
396 delete[] face_backs;
397 }
398
generate_vertex_faces()399 void xr_mesh_builder::generate_vertex_faces()
400 {
401 m_vertex_faces.assign(m_points.size(), BAD_IDX);
402 uint32_t face_idx = 0;
403 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end();
404 it != end; ++it, ++face_idx) {
405 it->link0 = m_vertex_faces[it->v0];
406 it->link1 = m_vertex_faces[it->v1];
407 it->link2 = m_vertex_faces[it->v2];
408 m_vertex_faces[it->v0] = face_idx;
409 m_vertex_faces[it->v1] = face_idx;
410 m_vertex_faces[it->v2] = face_idx;
411 }
412 }
413
find_edge(uint_fast32_t v0,uint_fast32_t v1)414 xr_mesh_builder::b_edge* xr_mesh_builder::find_edge(uint_fast32_t v0, uint_fast32_t v1)
415 {
416 for (uint_fast32_t next = m_vertex_edges[v0]; next != BAD_IDX;) {
417 b_edge* edge = &m_edges[next];
418 if (edge->v1 == v1)
419 return edge;
420 next = edge->link;
421 }
422 for (uint_fast32_t next = m_vertex_edges[v1]; next != BAD_IDX;) {
423 b_edge* edge = &m_edges[next];
424 if (edge->v1 == v0)
425 return edge;
426 next = edge->link;
427 }
428 return 0;
429 }
430
create_edges(bool calc_smoothness)431 void xr_mesh_builder::create_edges(bool calc_smoothness)
432 {
433 m_vertex_edges.assign(m_points.size(), BAD_IDX);
434 m_edges.clear();
435 m_edges.reserve(m_points.size());
436 uint32_t face_idx = 0;
437 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end();
438 it != end; ++it, ++face_idx) {
439 for (uint_fast32_t i = 3, v0, v1 = it->v0; i != 0; v1 = v0) {
440 b_edge* edge = find_edge(v0 = it->v[--i], v1);
441 if (edge == 0) {
442 it->link[i] = BAD_IDX;
443 uint32_t next = m_vertex_edges[v0];
444 m_vertex_edges[v0] = uint32_t(m_edges.size() & UINT32_MAX);
445 m_edges.push_back(b_edge(v1, face_idx, next));
446 } else {
447 it->link[i] = edge->face0;
448 if (!calc_smoothness) {
449 ++edge->size;
450 } else {
451 edge->smooth = (++edge->size == 2) ?
452 it->is_edge_smooth(m_faces[edge->face0], v0, v1) : false;
453 }
454 edge->face0 = face_idx;
455 }
456 }
457 }
458 }
459
460 ////////////////////////////////////////////////////////////////////////////////
461
create_smoothing_groups()462 void xr_mesh_builder::create_smoothing_groups()
463 {
464 if (m_normals.empty())
465 return;
466
467 create_edges(true);
468
469 m_sgroups.assign(m_faces.size(), EMESH_NO_SG);
470 std::vector<uint32_t> adjacents;
471 adjacents.reserve(512);
472 uint32_t sgroup = 0;
473 for (uint_fast32_t idx = uint32_t(m_faces.size() & UINT32_MAX); idx != 0;) {
474 if (m_sgroups[--idx] != EMESH_NO_SG)
475 continue;
476 uint32_t tag = m_faces[idx].tag;
477 bool new_sgroup = false;
478 for (uint_fast32_t face_idx = idx;;) {
479 const b_face& face = m_faces[face_idx];
480 for (uint_fast32_t i = 3, v0, v1 = face.v0; i != 0; v1 = v0) {
481 b_edge* edge = find_edge(v0 = face.v[--i], v1);
482 xr_assert(edge);
483 if (!edge->smooth)
484 continue;
485 if (!new_sgroup) {
486 new_sgroup = true;
487 m_sgroups[face_idx] = sgroup;
488 }
489 uint32_t adjacent = (edge->face0 == face_idx) ?
490 face.link[i] : edge->face0;
491 if (m_sgroups[adjacent] == EMESH_NO_SG &&
492 m_faces[adjacent].tag == tag) {
493 adjacents.push_back(adjacent);
494 m_sgroups[adjacent] = sgroup;
495 }
496 }
497 if (adjacents.empty())
498 break;
499 face_idx = adjacents.back();
500 adjacents.pop_back();
501 }
502 if (new_sgroup)
503 ++sgroup;
504 }
505 }
506
operator ()surface_pred507 struct surface_pred { bool operator()(const xr_mesh_builder::b_face* l, const xr_mesh_builder::b_face* r) const {
508 return l->surface < r->surface;
509 }};
510
compact_raw_surfaces()511 void xr_mesh_builder::compact_raw_surfaces()
512 {
513 b_face **refs = new b_face*[m_faces.size()];
514 b_face **ref = refs;
515 b_face **refs_end = refs + m_faces.size();
516 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end(); it != end; ++it)
517 *ref++ = &*it;
518 std::sort(refs, refs_end, surface_pred());
519
520 uint32_t surf_idx = 0;
521 for (ref = refs; ref != refs_end; ++surf_idx) {
522 b_face* face = *ref;
523 xr_raw_surface surface(face->surface);
524 m_raw_surfaces.push_back(surface);
525 face->surf_idx = surf_idx;
526 face->sgroup = EMESH_NO_SG;
527 while (++ref != refs_end && (face = *ref)->surface == surface) {
528 face->surf_idx = surf_idx;
529 face->sgroup = EMESH_NO_SG;
530 }
531 }
532 delete[] refs;
533 }
534
create_mappings(lw_face_vec & faces,lw_vmref_vec & vmrefs,xr_vmap_vec & vmaps,const xr_bone_vec & bones) const535 void xr_mesh_builder::create_mappings(lw_face_vec& faces, lw_vmref_vec& vmrefs, xr_vmap_vec& vmaps,
536 const xr_bone_vec& bones) const
537 {
538 xr_uv_vmap* uv_vmap = 0;
539 xr_face_uv_vmap* face_uv_vmap = 0;
540 uint32_t vert_idx = 0;
541 for (std::vector<uint32_t>::const_iterator it = m_vertex_faces.begin(),
542 end = m_vertex_faces.end(); it != end; ++it, ++vert_idx) {
543 if (*it == BAD_IDX) {
544 const fvector3& p = m_points[vert_idx];
545 msg("unused vertex %g,%g,%g", p.x, p.y, p.z);
546 continue;
547 }
548
549 lw_vmref vmref0;
550 uint32_t tc0 = BAD_IDX, vmref0_idx = 0;
551 for (uint32_t face_idx = *it; face_idx != BAD_IDX;) {
552 const b_face& face = m_faces[face_idx];
553 if (face_idx == BAD_IDX) {
554 face_idx = face.next_face_idx(vert_idx);
555 continue;
556 }
557 uint_fast32_t local_idx = face.local_vert_idx(vert_idx);
558 uint32_t tc = face.tc[local_idx], vmref_idx;
559 xr_assert(tc != BAD_IDX);
560 if (tc0 == BAD_IDX) {
561 if (uv_vmap == 0) {
562 uv_vmap = new xr_uv_vmap("Texture");
563 vmaps.push_back(uv_vmap);
564 }
565 vmref0.push_back(lw_vmref_entry(0, uv_vmap->add_uv(
566 m_texcoords[tc0 = tc], vert_idx)));
567 vmref0_idx = vmref_idx = uint32_t(vmrefs.size() & UINT32_MAX);
568 vmrefs.push_back(vmref0);
569 } else if (tc0 == tc) {
570 vmref_idx = vmref0_idx;
571 } else {
572 if (face_uv_vmap == 0) {
573 face_uv_vmap = new xr_face_uv_vmap("Texture");
574 vmaps.push_back(face_uv_vmap);
575 }
576 lw_vmref vmref;
577 vmref.push_back(lw_vmref_entry(1, face_uv_vmap->add_uv(
578 m_texcoords[tc], vert_idx, face_idx)));
579 vmref_idx = uint32_t(vmrefs.size() & UINT32_MAX);
580 vmrefs.push_back(vmref);
581 }
582 faces[face_idx].ref[local_idx] = vmref_idx;
583 face_idx = face.link[local_idx];
584 }
585 }
586 // bones.empty() check is required when trying to convert external LOD parts in older builds.
587 if (!m_influences.empty() && !bones.empty()) {
588 uint32_t offset = uint32_t(vmaps.size() & UINT32_MAX);
589 vmaps.resize(offset + bones.size());
590 lw_vmref_vec weight_vmrefs(m_influences.size());
591 vert_idx = 0;
592 for (std::vector<finfluence>::const_iterator it = m_influences.begin(),
593 end = m_influences.end(); it != end; ++it, ++vert_idx) {
594 for (finfluence::const_iterator it1 = it->begin(), end1 = it->end();
595 it1 != end1; ++it1) {
596 xr_weight_vmap* weight_vmap = static_cast<xr_weight_vmap*>(vmaps.at(offset + it1->bone));
597 if (weight_vmap == 0) {
598 vmaps[offset + it1->bone] = weight_vmap =
599 new xr_weight_vmap(bones.at(it1->bone)->name());
600 }
601 uint32_t weight_idx = weight_vmap->add_weight(it1->weight, vert_idx);
602 xr_assert(!weight_vmrefs[vert_idx].full());
603 weight_vmrefs[vert_idx].push_back(lw_vmref_entry(offset + it1->bone, weight_idx));
604 }
605 }
606 for (lw_face_vec_it it = faces.begin(), end = faces.end(); it != end; ++it) {
607 for (uint_fast32_t i = 3; i != 0;) {
608 lw_vmref& vmref = vmrefs[it->ref[--i]];
609 if (vmref.size() > 1)
610 continue;
611 vmref.append(weight_vmrefs[it->v[i]]);
612 }
613 }
614 }
615 uint32_t* vmap_remap = new uint32_t[vmaps.size()];
616 unsigned used = 0;
617 for (uint_fast32_t i = 0, n = vmaps.size(); i != n; ++i) {
618 if (i != used)
619 vmaps[used] = vmaps[i];
620 vmap_remap[i] = vmaps[i] ? used++ : BAD_IDX;
621 }
622 vmaps.resize(used);
623 for (lw_vmref_vec_it it = vmrefs.begin(), end = vmrefs.end(); it != end; ++it) {
624 for (lw_vmref::iterator it1 = it->begin(), end1 = it->end(); it1 != end1; ++it1)
625 it1->vmap = vmap_remap[it1->vmap];
626 }
627 delete[] vmap_remap;
628 }
629
commit(xr_object & object)630 void xr_mesh_builder::commit(xr_object& object)
631 {
632 compact_raw_surfaces();
633 m_surfmaps.reserve(m_raw_surfaces.size());
634 for (xr_raw_surface_vec_it it = m_raw_surfaces.begin(), end = m_raw_surfaces.end();
635 it != end; ++it) {
636 xr_surfmap* smap = new xr_surfmap(object.attach(*it));
637 m_surfmaps.push_back(smap);
638 }
639 xr_raw_surface_vec().swap(m_raw_surfaces);
640
641 create_smoothing_groups();
642 std::vector<fvector3>().swap(m_normals);
643 b_edge_vec().swap(m_edges);
644 std::vector<uint32_t>().swap(m_vertex_edges);
645
646 xr_mesh::m_faces.reserve(m_faces.size());
647 uint32_t face_idx = 0;
648 for (b_face_vec_it it = m_faces.begin(), end = m_faces.end();
649 it != end; ++it, ++face_idx) {
650 xr_mesh::m_faces.push_back(lw_face(it->v0, it->v1, it->v2));
651 xr_assert(it->surf_idx != BAD_IDX);
652 m_surfmaps[it->surf_idx]->faces.push_back(face_idx);
653 }
654
655 generate_vertex_faces();
656 create_mappings(xr_mesh::m_faces, m_vmrefs, m_vmaps, object.bones());
657 std::vector<fvector2>().swap(m_texcoords);
658 std::vector<finfluence>().swap(m_influences);
659 std::vector<uint32_t>().swap(m_vertex_faces);
660 b_face_vec().swap(m_faces);
661
662 calculate_bbox();
663
664 object.meshes().push_back(this);
665 }
666
remove_empty_surfmaps()667 void xr_mesh_builder::remove_empty_surfmaps()
668 {
669 xr_surfmap_vec_it last = m_surfmaps.begin();
670 for (xr_surfmap_vec_it it = last, end = m_surfmaps.end(); it != end; ++it) {
671 xr_surfmap* smap = *it;
672 if (smap->faces.empty()) {
673 delete smap;
674 continue;
675 }
676 if (it != last)
677 *last = smap;
678 ++last;
679 }
680 m_surfmaps.erase(last, m_surfmaps.end());
681 }
682