1 #include <algorithm>
2 #include "xr_object.h"
3 #include "xr_object_format.h"
4 #include "xr_motion.h"
5 #include "xr_bone.h"
6 #include "xr_mesh.h"
7 #include "xr_surface.h"
8 #include "xr_reader.h"
9 #include "xr_writer.h"
10 #include "xr_file_system.h"
11 #include "xr_string_utils.h"
12 #include "xr_utils.h"
13 #include "xr_name_gen.h"
14 
15 using namespace xray_re;
16 
xr_object()17 xr_object::xr_object(): m_flags(EOF_STATIC),
18 	m_owner_name("unknown"), m_creation_time(0),
19 	m_modif_name("unknown"), m_modified_time(0),
20 	m_surface_factory(0)
21 {
22 	m_position.set();
23 	m_rotation.set();
24 }
25 
xr_object(const xr_surface_factory * surface_factory)26 xr_object::xr_object(const xr_surface_factory* surface_factory):
27 	m_flags(EOF_STATIC),
28 	m_owner_name("unknown"), m_creation_time(0),
29 	m_modif_name("unknown"), m_modified_time(0),
30 	m_surface_factory(surface_factory)
31 {
32 	m_position.set();
33 	m_rotation.set();
34 }
35 
~xr_object()36 xr_object::~xr_object()
37 {
38 	delete_elements(m_surfaces);
39 	delete_elements(m_meshes);
40 	delete_elements(m_bones);
41 	delete_elements(m_motions);
42 	delete_elements(m_partitions);
43 }
44 
clear()45 void xr_object::clear()
46 {
47 	m_flags = EOF_STATIC;
48 	m_owner_name = "unknown";
49 	m_creation_time = 0;
50 	m_modif_name = "unknown";
51 	m_modified_time = 0;
52 	clear_container(m_surfaces);
53 	clear_container(m_meshes);
54 	clear_container(m_bones);
55 	clear_container(m_motions);
56 	clear_container(m_partitions);
57 }
58 
setup_bones()59 void xr_object::setup_bones()
60 {
61 	uint16_t bone_id = 0;
62 	for (xr_bone_vec_it it = m_bones.begin(), end = m_bones.end();
63 			it != end; ++it, ++bone_id) {
64 		(*it)->setup(bone_id, *this);
65 	}
66 }
67 
calculate_bind()68 void xr_object::calculate_bind()
69 {
70 	for (xr_bone_vec_it it = m_bones.begin(), end = m_bones.end(); it != end; ++it) {
71 		if ((*it)->is_root()) {
72 			(*it)->calculate_bind(fmatrix().identity());
73 			break;
74 		}
75 	}
76 }
77 
root_bone() const78 const xr_bone* xr_object::root_bone() const
79 {
80 	for (xr_bone_vec_cit it = m_bones.begin(), end = m_bones.end(); it != end; ++it) {
81 		if ((*it)->is_root())
82 			return *it;
83 	}
84 	return 0;
85 }
86 
setup_partitions()87 void xr_object::setup_partitions()
88 {
89 	uint16_t part_id = 0;
90 	for (xr_partition_vec_it it = m_partitions.begin(),
91 			end = m_partitions.end(); it != end; ++it) {
92 		(*it)->setup(part_id++);
93 	}
94 }
95 
96 struct read_mesh {
97 	xr_object& object;
read_meshread_mesh98 	read_mesh(xr_object& _object): object(_object) {}
operator ()read_mesh99 	void operator()(xr_mesh*& mesh, xr_reader& r) {
100 		mesh = new xr_mesh;
101 		mesh->load(r, object);
102 	}
103 };
104 
105 struct read_partition_0 {
106 	xr_bone_vec& all_bones;
read_partition_0read_partition_0107 	read_partition_0(xr_bone_vec& _all_bones): all_bones(_all_bones) {}
operator ()read_partition_0108 	void operator()(xr_partition*& part, xr_reader& r) {
109 		part = new xr_partition;
110 		part->load_0(r, all_bones);
111 	}
112 };
113 
load_object(xr_reader & r)114 void xr_object::load_object(xr_reader& r)
115 {
116 	uint16_t version;
117 	if (!r.r_chunk<uint16_t>(EOBJ_CHUNK_VERSION, version))
118 		xr_not_expected();
119 	xr_assert(version == EOBJ_VERSION);
120 
121 	if (!r.r_chunk<uint32_t>(EOBJ_CHUNK_FLAGS, m_flags))
122 		xr_not_expected();
123 
124 	if (r.find_chunk(EOBJ_CHUNK_USERDATA)) {
125 		r.r_sz(m_userdata);
126 		r.debug_find_chunk();
127 	}
128 
129 	if (r.find_chunk(EOBJ_CHUNK_LOD_REF)) {
130 		r.r_sz(m_lod_ref);
131 		r.debug_find_chunk();
132 	}
133 
134 	if (r.find_chunk(EOBJ_CHUNK_SURFACES_2)) {
135 		r.r_seq(r.r_u32(), m_surfaces, xr_reader::f_r_new<xr_surface>(&xr_surface::load_2));
136 		r.debug_find_chunk();
137 	} else if (r.find_chunk(EOBJ_CHUNK_SURFACES_1)) {
138 		r.r_seq(r.r_u32(), m_surfaces, xr_reader::f_r_new<xr_surface>(&xr_surface::load_1));
139 		r.debug_find_chunk();
140 	} else if (r.find_chunk(EOBJ_CHUNK_SURFACES_0)) {
141 		r.r_seq(r.r_u32(), m_surfaces, xr_reader::f_r_new<xr_surface>(&xr_surface::load_0));
142 		r.debug_find_chunk();
143 		if (r.find_chunk(EOBJ_CHUNK_SHADERS_0)) {
144 			for (xr_surface_vec_it it = m_surfaces.begin(), end = m_surfaces.end();
145 					it != end; ++it) {
146 				(*it)->cshader() = r.skip_sz();
147 			}
148 			r.debug_find_chunk();
149 		}
150 	} else {
151 		xr_not_expected();
152 	}
153 
154 	xr_reader* s = r.open_chunk(EOBJ_CHUNK_MESHES);
155 	if (s) {
156 		s->r_chunks(m_meshes, read_mesh(*this));
157 		r.close_chunk(s);
158 	}
159 
160 	s = r.open_chunk(EOBJ_CHUNK_BONES_1);
161 	if (s) {
162 		s->r_chunks(m_bones, xr_reader::f_r_new<xr_bone>(&xr_bone::load_1));
163 		r.close_chunk(s);
164 	} else if (r.find_chunk(EOBJ_CHUNK_BONES_0)) {
165 		s->r_seq(r.r_u32(), m_bones, xr_reader::f_r_new<xr_bone>(&xr_bone::load_0));
166 		r.debug_find_chunk();
167 	}
168 	setup_bones();
169 	if (r.find_chunk(EOBJ_CHUNK_MOTIONS)) {
170 		r.r_seq(r.r_u32(), m_motions, xr_reader::f_r_new<xr_skl_motion>(&xr_skl_motion::load));
171 		r.debug_find_chunk();
172 	}
173 	if (r.find_chunk(EOBJ_CHUNK_MOTION_REFS)) {
174 		r.r_sz(m_motion_refs);
175 		r.debug_find_chunk();
176 	}
177 	if (r.find_chunk(EOBJ_CHUNK_PARTITIONS_0)) {
178 		r.r_seq(r.r_u32(), m_partitions, read_partition_0(m_bones));
179 		r.debug_find_chunk();
180 	} else if (r.find_chunk(EOBJ_CHUNK_PARTITIONS_1)) {
181 		r.r_seq(r.r_u32(), m_partitions, xr_reader::f_r_new<xr_partition>(&xr_partition::load_1));
182 		r.debug_find_chunk();
183 	}
184 	if (r.find_chunk(EOBJ_CHUNK_TRANSFORM)) {
185 		r.r_fvector3(m_position);
186 		r.r_fvector3(m_rotation);
187 		r.debug_find_chunk();
188 	}
189 	if (r.find_chunk(EOBJ_CHUNK_REVISION)) {
190 		r.r_sz(m_owner_name);
191 		m_creation_time = r.r_u32();
192 		r.r_sz(m_modif_name);
193 		m_modified_time = r.r_u32();
194 		r.debug_find_chunk();
195 	}
196 }
197 
load_object(const char * path)198 bool xr_object::load_object(const char* path)
199 {
200 	xr_file_system& fs = xr_file_system::instance();
201 	xr_reader* r = fs.r_open(path);
202 	if (r == 0)
203 		return false;
204 	bool status = false;
205 	xr_reader* s = r->open_chunk(EOBJ_CHUNK_MAIN);
206 	if (s) {
207 		try {
208 			load_object(*s);
209 			status = true;
210 		} catch (xr_error) {
211 			clear();
212 		}
213 		r->close_chunk(s);
214 	}
215 	fs.r_close(r);
216 	return status;
217 }
218 
save_object(xr_writer & w) const219 void xr_object::save_object(xr_writer& w) const
220 {
221 	w.w_chunk<uint16_t>(EOBJ_CHUNK_VERSION, EOBJ_VERSION);
222 
223 	w.w_chunk(EOBJ_CHUNK_USERDATA, m_userdata);
224 
225 	w.w_chunk(EOBJ_CHUNK_LOD_REF, m_lod_ref);
226 
227 	w.w_chunk<uint32_t>(EOBJ_CHUNK_FLAGS, m_flags);
228 
229 	w.open_chunk(EOBJ_CHUNK_MESHES);
230 	w.w_chunks(m_meshes, xr_writer::f_w_const<xr_mesh>(&xr_mesh::save));
231 	w.close_chunk();
232 
233 	w.open_chunk(EOBJ_CHUNK_SURFACES_2);
234 	w.w_size_u32(m_surfaces.size());
235 	w.w_seq(m_surfaces, xr_writer::f_w_const<xr_surface>(&xr_surface::save));
236 	w.close_chunk();
237 
238 	if (!m_bones.empty()) {
239 		w.open_chunk(EOBJ_CHUNK_BONES_1);
240 		w.w_chunks(m_bones, xr_writer::f_w_const<xr_bone>(&xr_bone::save));
241 		w.close_chunk();
242 	}
243 	if (!m_motions.empty()) {
244 		w.open_chunk(EOBJ_CHUNK_MOTIONS);
245 		w.w_size_u32(m_motions.size());
246 		w.w_seq(m_motions, xr_writer::f_w_const<xr_skl_motion>(&xr_skl_motion::save));
247 		w.close_chunk();
248 	}
249 	if (!m_motion_refs.empty()) {
250 		w.w_chunk(EOBJ_CHUNK_MOTION_REFS, m_motion_refs);
251 	}
252 	if (!m_partitions.empty()) {
253 		w.open_chunk(EOBJ_CHUNK_PARTITIONS_1);
254 		w.w_size_u32(m_partitions.size());
255 		w.w_seq(m_partitions, xr_writer::f_w_const<xr_partition>(&xr_partition::save));
256 		w.close_chunk();
257 	}
258 	if (m_flags & EOF_DYNAMIC) {
259 		w.open_chunk(EOBJ_CHUNK_TRANSFORM);
260 		w.w_fvector3(m_position);
261 		w.w_fvector3(m_rotation);
262 		w.close_chunk();
263 	}
264 
265 	w.open_chunk(EOBJ_CHUNK_REVISION);
266 	w.w_sz(m_owner_name);
267 	w.w_u32(m_creation_time);
268 	w.w_sz(m_modif_name);
269 	w.w_u32(m_modified_time);
270 	w.close_chunk();
271 }
272 
save_object(const char * path) const273 bool xr_object::save_object(const char* path) const
274 {
275 	xr_memory_writer* w = new xr_memory_writer();
276 	w->open_chunk(EOBJ_CHUNK_MAIN);
277 	save_object(*w);
278 	w->close_chunk();
279 	bool status = w->save_to(path);
280 	delete w;
281 	return status;
282 }
283 
save_object(const char * path,const std::string & name) const284 bool xr_object::save_object(const char* path, const std::string& name) const
285 {
286 	xr_memory_writer* w = new xr_memory_writer();
287 	w->open_chunk(EOBJ_CHUNK_MAIN);
288 	save_object(*w);
289 	w->close_chunk();
290 	bool status = w->save_to(path, name);
291 	delete w;
292 	return status;
293 }
294 
load_bones(xr_reader & r)295 void xr_object::load_bones(xr_reader& r)
296 {
297 	r.r_chunks(m_bones, xr_reader::f_r_new<xr_bone>(&xr_bone::load_data));
298 	if (r.find_chunk(EOBJ_CHUNK_PARTITIONS_1)) {
299 		r.r_seq(r.r_u32(), m_partitions, xr_reader::f_r_new<xr_partition>(&xr_partition::load_1));
300 		r.debug_find_chunk();
301 	}
302 }
303 
load_bones(const char * path)304 bool xr_object::load_bones(const char* path)
305 {
306 	xr_file_system& fs = xr_file_system::instance();
307 	xr_reader* r = fs.r_open(path);
308 	if (r == 0)
309 		return false;
310 	bool status = false;
311 	try {
312 		load_bones(*r);
313 		status = true;
314 	} catch (xr_error) {
315 		clear();
316 	}
317 	fs.r_close(r);
318 	return status;
319 }
320 
save_bones(xr_writer & w) const321 void xr_object::save_bones(xr_writer& w) const
322 {
323 	w.w_chunks(m_bones, xr_writer::f_w_const<xr_bone>(&xr_bone::save_data));
324 	w.open_chunk(EOBJ_CHUNK_PARTITIONS_1);
325 	w.w_size_u32(m_partitions.size());
326 	w.w_seq(m_partitions, xr_writer::f_w_const<xr_partition>(&xr_partition::save));
327 	w.close_chunk();
328 }
329 
save_bones(const char * path) const330 bool xr_object::save_bones(const char* path) const
331 {
332 	xr_memory_writer* w = new xr_memory_writer();
333 	save_bones(*w);
334 	bool status = w->save_to(path);
335 	delete w;
336 	return status;
337 }
338 
load_skls(xr_reader & r)339 void xr_object::load_skls(xr_reader& r)
340 {
341 	r.r_seq(r.r_u32(), m_motions, xr_reader::f_r_new<xr_skl_motion>(&xr_skl_motion::load));
342 }
343 
load_skls(const char * path)344 bool xr_object::load_skls(const char* path)
345 {
346 	xr_file_system& fs = xr_file_system::instance();
347 	xr_reader* r = fs.r_open(path);
348 	if (r == 0)
349 		return false;
350 	bool status = false;
351 	try {
352 		load_skls(*r);
353 		status = true;
354 	} catch (xr_error) {
355 		clear();
356 	}
357 	fs.r_close(r);
358 	return status;
359 }
360 
save_skls(xr_writer & w) const361 void xr_object::save_skls(xr_writer& w) const
362 {
363 	w.w_size_u32(m_motions.size());
364 	w.w_seq(m_motions, xr_writer::f_w_const<xr_skl_motion>(&xr_skl_motion::save));
365 }
366 
save_skls(const char * path) const367 bool xr_object::save_skls(const char* path) const
368 {
369 	xr_memory_writer* w = new xr_memory_writer();
370 	save_skls(*w);
371 	bool status = w->save_to(path);
372 	delete w;
373 	return status;
374 }
375 
operator ()surface_name_pred376 struct surface_name_pred { bool operator()(const xr_surface* l, const xr_surface* r) const {
377 	return l->name() < r->name();
378 }};
379 
denominate_surfaces()380 void xr_object::denominate_surfaces()
381 {
382 	for (xr_surface_vec_it it = m_surfaces.begin(), end = m_surfaces.end(); it != end; ++it) {
383 		xr_surface* surface = *it;
384 		const std::string& texture = surface->texture();
385 		std::string::size_type pos = texture.rfind('\\');
386 		if (pos == std::string::npos)
387 			pos = 0;
388 		else
389 			++pos;
390 		std::string& name = surface->name();
391 		name.reserve(texture.size() - pos + 3);
392 		for (std::string::const_iterator it1 = texture.begin() + pos,
393 				end1 = texture.end(); it1 != end1; ++it1) {
394 			int c = *it1;
395 			name.push_back(std::isalnum(c) ? char(std::tolower(c)) : '_');
396 		}
397 		name += "_S";
398 	}
399 	std::sort(m_surfaces.begin(), m_surfaces.end(), surface_name_pred());
400 	char suffix[8];
401 	for (xr_surface_vec_it it = m_surfaces.begin(), end = m_surfaces.end(); it != end;) {
402 		const std::string& name = (*it)->name();
403 		for (unsigned i = 1; ++it != end && (*it)->name() == name; ++i) {
404 			xr_snprintf(suffix, sizeof(suffix), "%u", i);
405 			(*it)->name() += suffix;
406 		}
407 	}
408 }
409 
denominate()410 void xr_object::denominate()
411 {
412 	denominate_surfaces();
413 	xr_name_gen name("mesh", false);
414 	for (xr_mesh_vec_it it = m_meshes.begin(), end = m_meshes.end(); it != end; ++it, name.next())
415 		(*it)->name().assign(name.get()).append("Shape");
416 }
417 
to_object()418 void xr_object::to_object() {}
419 
attach(const xr_raw_surface & raw_surface)420 xr_surface* xr_object::attach(const xr_raw_surface& raw_surface)
421 {
422 	xr_surface*& surface = m_raw_surfaces[raw_surface];
423 	if (surface == 0) {
424 		surface = m_surface_factory ?
425 				m_surface_factory->create_surface(raw_surface) :
426 				create_surface(raw_surface);
427 		xr_assert(surface);
428 		m_surfaces.push_back(surface);
429 	}
430 	return surface;
431 }
432 
create_surface(const xr_raw_surface & raw_surface) const433 xr_surface* xr_object::create_surface(const xr_raw_surface& raw_surface) const { return 0; }
434 
find_surface(const std::string & name)435 xr_surface* xr_object::find_surface(const std::string& name) { return find_by_name(m_surfaces, name); }
find_mesh(const std::string & name)436 xr_mesh* xr_object::find_mesh(const std::string& name) { return find_by_name(m_meshes, name); }
find_bone(const std::string & name)437 xr_bone* xr_object::find_bone(const std::string& name) { return find_by_name(m_bones, name); }
find_partition(const std::string & name)438 xr_partition* xr_object::find_partition(const std::string& name) { return find_by_name(m_partitions, name); }
find_motion(const std::string & name)439 xr_skl_motion* xr_object::find_motion(const std::string& name) { return find_by_name(m_motions, name); }
440