1 #include <algorithm>
2 #include "xr_cform.h"
3 #include "xr_reader.h"
4 #include "xr_writer.h"
5 
6 using namespace xray_re;
7 
xr_cform()8 xr_cform::xr_cform() { m_bbox.null(); }
9 
~xr_cform()10 xr_cform::~xr_cform() {}
11 
operator ()read_vertex12 struct read_vertex { void operator()(cf_vertex& vertex, xr_reader& r) const {
13 	r.r_fvector3(vertex.p);
14 	vertex.face0 = BAD_IDX;
15 }};
16 
operator ()read_face_v217 struct read_face_v2 { void operator()(cf_face& face, xr_reader& r) const {
18 	face.v0 = r.r_u32();
19 	face.v1 = r.r_u32();
20 	face.v2 = r.r_u32();
21 	r.advance(12+2);
22 	face.sector = r.r_u16();
23 	r.advance(4);
24 	face.link0 = BAD_IDX;
25 	face.link1 = BAD_IDX;
26 	face.link2 = BAD_IDX;
27 }};
28 
operator ()read_face_v429 struct read_face_v4 { void operator()(cf_face& face, xr_reader& r) const {
30 	face.v0 = r.r_u32();
31 	face.v1 = r.r_u32();
32 	face.v2 = r.r_u32();
33 	face.link0 = BAD_IDX;
34 	face.link1 = BAD_IDX;
35 	face.link2 = BAD_IDX;
36 	face.dummy = r.r_u32();
37 }};
38 
load(xr_reader & r)39 void xr_cform::load(xr_reader& r)
40 {
41 	uint32_t version = r.r_u32();
42 	xr_assert(version >= CFORM_VERSION_2 && version <= CFORM_VERSION_4);
43 	size_t vertex_count = r.r_u32();
44 	size_t face_count = r.r_u32();
45 	r.r_fvector3(m_bbox.min);
46 	r.r_fvector3(m_bbox.max);
47 	r.r_seq(vertex_count, m_vertices, read_vertex());
48 	if (version == CFORM_VERSION_2 || version == CFORM_VERSION_3)
49 		r.r_seq(face_count, m_faces, read_face_v2());
50 	else if (version == CFORM_VERSION_4)
51 		r.r_seq(face_count, m_faces, read_face_v4());
52 }
53 
operator ()write_vertex54 struct write_vertex { void operator()(const cf_vertex& vertex, xr_writer& w) const {
55 	w.w_fvector3(vertex.p);
56 }};
57 
operator ()write_face_v458 struct write_face_v4 { void operator()(const cf_face& face, xr_writer& w) const {
59 	w.w_u32(face.v0);
60 	w.w_u32(face.v1);
61 	w.w_u32(face.v2);
62 	w.w_u32(face.dummy);
63 }};
64 
save(xr_writer & w) const65 void xr_cform::save(xr_writer& w) const
66 {
67 	w.w_u32(CFORM_VERSION_4);
68 	w.w_size_u32(m_vertices.size());
69 	w.w_size_u32(m_faces.size());
70 	w.w_fvector3(m_bbox.min);
71 	w.w_fvector3(m_bbox.max);
72 	w.w_seq(m_vertices, write_vertex());
73 	w.w_seq(m_faces, write_face_v4());
74 }
75 
generate_vertex_faces()76 void xr_cform::generate_vertex_faces()
77 {
78 	for (cf_vertex_vec_it it = m_vertices.begin(), end = m_vertices.end();
79 			it != end; ++it) {
80 		it->face0 = BAD_IDX;
81 	}
82 	uint32_t face_idx = 0;
83 	for (cf_face_vec_it it = m_faces.begin(), end = m_faces.end();
84 			it != end; ++it, ++face_idx) {
85 		for (uint_fast32_t i = 3; i != 0;) {
86 			uint32_t& face0 = m_vertices[it->v[--i]].face0;
87 			it->link[i] = face0;
88 			face0 = face_idx;
89 		}
90 	}
91 }
92 
is_duplicate(const cf_face & face) const93 bool cf_face::is_duplicate(const cf_face& face) const
94 {
95 	for (uint_fast32_t i = 3; i != 0;) {
96 		if (v[--i] != face.v0)
97 			continue;
98 		return v[(i+1)%3] == face.v1 && v[(i+2)%3] == face.v2 &&
99 				dummy == face.dummy;
100 	}
101 	return false;
102 }
103 
operator ()face_degenerate_pred104 struct face_degenerate_pred { bool operator()(const cf_face& face) const {
105 	return face.v0 == face.v1 || face.v1 == face.v2 || face.v2 == face.v0;
106 }};
107 
operator ()face_duplicate_pred108 struct face_duplicate_pred { bool operator()(const cf_face& face) const {
109 	return face.dummy == BAD_IDX;
110 }};
111 
optimize()112 void xr_cform::optimize()
113 {
114 	m_faces.erase(std::remove_if(m_faces.begin(), m_faces.end(), face_degenerate_pred()), m_faces.end());
115 
116 	generate_vertex_faces();
117 	for (cf_face_vec_it it = m_faces.begin(), end = m_faces.end(); it != end; ++it) {
118 		if (it->dummy == BAD_IDX)
119 			continue;
120 		for (uint_fast32_t next = m_vertices[it->v0].face0; next != BAD_IDX;) {
121 			cf_face& face = m_faces[next];
122 			if (&face > &*it && it->is_duplicate(face))
123 				face.dummy = BAD_IDX;
124 			next = face.next_face_idx(it->v0);
125 		}
126 	}
127 //	size_t n = count_if(m_faces.begin(), m_faces.end(), is_duplicate());
128 	m_faces.erase(std::remove_if(m_faces.begin(), m_faces.end(), face_duplicate_pred()), m_faces.end());
129 //	msg("CFORM optimize: was %"PRIuSIZE", left: %"PRIuSIZE"\n", n, m_faces.size());
130 
131 	generate_vertex_faces();
132 }
133