Panda3D
fltTexture.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file fltTexture.cxx
10  * @author drose
11  * @date 2000-08-25
12  */
13 
14 #include "fltTexture.h"
15 #include "fltRecordReader.h"
16 #include "fltRecordWriter.h"
17 #include "fltHeader.h"
18 #include "pathReplace.h"
19 #include "config_putil.h"
20 
21 TypeHandle FltTexture::_type_handle;
22 
23 /**
24  *
25  */
26 FltTexture::
27 FltTexture(FltHeader *header) : FltRecord(header) {
28  _pattern_index = -1;
29  _x_location = 0;
30  _y_location = 0;
31 
32  _num_texels_u = 0;
33  _num_texels_v = 0;
34  _real_world_size_u = 0;
35  _real_world_size_v = 0;
36  _up_vector_x = 0;
37  _up_vector_y = 1;
38  _file_format = FF_none;
39  _min_filter = MN_point;
40  _mag_filter = MG_point;
41  _repeat = RT_repeat;
42  _repeat_u = RT_repeat;
43  _repeat_v = RT_repeat;
44  _modify_flag = 0;
45  _x_pivot_point = 0;
46  _y_pivot_point = 0;
47  _env_type = ET_modulate;
48  _intensity_is_alpha = false;
49  _float_real_world_size_u = 0.0;
50  _float_real_world_size_v = 0.0;
51  _imported_origin_code = 0;
52  _kernel_version = 1520;
53  _internal_format = IF_default;
54  _external_format = EF_default;
55  _use_mipmap_kernel = false;
56  memset(_mipmap_kernel, 0, sizeof(_mipmap_kernel));
57  _use_lod_scale = false;
58  memset(_lod_scale, 0, sizeof(_lod_scale));
59  _clamp = 0.0;
60  _mag_filter_alpha = MG_point;
61  _mag_filter_color = MG_point;
62  _lambert_conic_central_meridian = 0.0;
63  _lambert_conic_upper_latitude = 0.0;
64  _lambert_conic_lower_latitude = 0.0;
65  _use_detail = false;
66  _detail_j = 0;
67  _detail_k = 0;
68  _detail_m = 0;
69  _detail_n = 0;
70  _detail_scramble = 0;
71  _use_tile = false;
72  _tile_lower_left_u = 0.0;
73  _tile_lower_left_v = 0.0;
74  _tile_upper_right_u = 0.0;
75  _tile_upper_right_v = 0.0;
76  _projection = PT_flat_earth;
77  _earth_model = EM_wgs84;
78  _utm_zone = 0;
79  _image_origin = IO_lower_left;
80  _geospecific_points_units = PU_degrees;
81  _geospecific_hemisphere = H_southern;
82  _file_version = 1501;
83 }
84 
85 /**
86  * Walks the hierarchy at this record and below and copies the
87  * _converted_filename record into the _orig_filename record, so the flt file
88  * will be written out with the converted filename instead of what was
89  * originally read in.
90  */
91 void FltTexture::
93  _orig_filename = _converted_filename.to_os_generic();
95 }
96 
97 /**
98  * Returns the name of the texture image file.
99  */
102  return _converted_filename;
103 }
104 
105 /**
106  * Changes the name of the texture image file.
107  */
108 void FltTexture::
109 set_texture_filename(const Filename &filename) {
110  _converted_filename = filename;
111  _orig_filename = _converted_filename.to_os_generic();
112 }
113 
114 /**
115  * Returns the name of the texture's associated .attr file. This contains
116  * some additional MultiGen information about the texture parameters. This
117  * is, of course, just the name of the texture with .attr appended.
118  *
119  * Normally, it won't be necessary to access this file directly; you can call
120  * read_attr_data() or write_attr_data() to get at the data stored in this
121  * file. (And read_attr_data() is called automatically when the Flt file is
122  * read in.)
123  */
126  std::string texture_filename = get_texture_filename();
127  return Filename::binary_filename(texture_filename + ".attr");
128 }
129 
130 /**
131  * Opens up the texture's .attr file and reads its data into the extra
132  * FltTexture fields. This is normally performed automatically when the Flt
133  * file is read from disk.
134  */
135 FltError FltTexture::
137  Filename attr_filename = get_attr_filename();
138 
139  std::ifstream attr;
140  if (!attr_filename.open_read(attr)) {
141  return FE_could_not_open;
142  }
143 
144  // Determine the file's size so we can read it all into one big datagram.
145  attr.seekg(0, std::ios::end);
146  if (attr.fail()) {
147  return FE_read_error;
148  }
149  std::streampos length = attr.tellg();
150 
151  char *buffer = new char[length];
152 
153  attr.seekg(0, std::ios::beg);
154  attr.read(buffer, length);
155  if (attr.fail()) {
156  return FE_read_error;
157  }
158 
159  Datagram datagram(buffer, length);
160  delete[] buffer;
161 
162  return unpack_attr(datagram);
163 }
164 
165 /**
166  * Writes the texture's .attr file. This may or may not be performed
167  * automatically, according to the setting of
168  * FltHeader::set_auto_attr_update().
169  */
170 FltError FltTexture::
173 }
174 
175 /**
176  * Writes the texture's .attr file to the named file.
177  */
178 FltError FltTexture::
179 write_attr_data(Filename attr_filename) const {
180  Datagram datagram;
181  FltError result = pack_attr(datagram);
182  if (result != FE_ok) {
183  return result;
184  }
185 
186  attr_filename.set_binary();
187  std::ofstream attr;
188  if (!attr_filename.open_write(attr)) {
189  return FE_could_not_open;
190  }
191 
192  attr.write((const char *)datagram.get_data(), datagram.get_length());
193  if (attr.fail()) {
194  return FE_write_error;
195  }
196  return FE_ok;
197 }
198 
199 /**
200  * Fills in the information in this record based on the information given in
201  * the indicated datagram, whose opcode has already been read. Returns true
202  * on success, false if the datagram is invalid.
203  */
204 bool FltTexture::
205 extract_record(FltRecordReader &reader) {
206  if (!FltRecord::extract_record(reader)) {
207  return false;
208  }
209 
210  nassertr(reader.get_opcode() == FO_texture, false);
211  DatagramIterator &iterator = reader.get_iterator();
212 
213  if (_header->get_flt_version() < 1420) {
214  _orig_filename = iterator.get_fixed_string(80);
215  } else {
216  _orig_filename = iterator.get_fixed_string(200);
217  }
218  _converted_filename = _header->convert_path(Filename::from_os_specific(_orig_filename), get_model_path());
219  _pattern_index = iterator.get_be_int32();
220  _x_location = iterator.get_be_int32();
221  _y_location = iterator.get_be_int32();
222 
223  if (read_attr_data() != FE_ok) {
224  nout << "Unable to read attribute file " << get_attr_filename() << "\n";
225  }
226 
227  check_remaining_size(iterator);
228  return true;
229 }
230 
231 /**
232  * Fills up the current record on the FltRecordWriter with data for this
233  * record, but does not advance the writer. Returns true on success, false if
234  * there is some error.
235  */
236 bool FltTexture::
237 build_record(FltRecordWriter &writer) const {
238  if (!FltRecord::build_record(writer)) {
239  return false;
240  }
241 
242  writer.set_opcode(FO_texture);
243  Datagram &datagram = writer.update_datagram();
244 
245  datagram.add_fixed_string(_orig_filename, 200);
246  datagram.add_be_int32(_pattern_index);
247  datagram.add_be_int32(_x_location);
248  datagram.add_be_int32(_y_location);
249 
250  if (_header->get_auto_attr_update() == FltHeader::AU_always ||
251  (_header->get_auto_attr_update() == FltHeader::AU_if_missing &&
252  !get_attr_filename().exists())) {
253  if (write_attr_data() != FE_ok) {
254  nout << "Unable to write attribute file " << get_attr_filename() << "\n";
255  }
256  }
257 
258  return true;
259 }
260 
261 /**
262  * Reads the data from the attribute file.
263  */
264 FltError FltTexture::
265 unpack_attr(const Datagram &datagram) {
266  DatagramIterator iterator(datagram);
267 
268  _num_texels_u = iterator.get_be_int32();
269  _num_texels_v = iterator.get_be_int32();
270  _real_world_size_u = iterator.get_be_int32();
271  _real_world_size_v = iterator.get_be_int32();
272  _up_vector_x = iterator.get_be_int32();
273  _up_vector_y = iterator.get_be_int32();
274  _file_format = (FileFormat)iterator.get_be_int32();
275  _min_filter = (Minification)iterator.get_be_int32();
276  _mag_filter = (Magnification)iterator.get_be_int32();
277  _repeat = (RepeatType)iterator.get_be_int32();
278  _repeat_u = (RepeatType)iterator.get_be_int32();
279  _repeat_v = (RepeatType)iterator.get_be_int32();
280  _modify_flag = iterator.get_be_int32();
281  _x_pivot_point = iterator.get_be_int32();
282  _y_pivot_point = iterator.get_be_int32();
283  _env_type = (EnvironmentType)iterator.get_be_int32();
284  _intensity_is_alpha = (iterator.get_be_int32() != 0);
285  iterator.skip_bytes(4 * 8);
286  iterator.skip_bytes(4); // Undocumented padding.
287  _float_real_world_size_u = iterator.get_be_float64();
288  _float_real_world_size_v = iterator.get_be_float64();
289  _imported_origin_code = iterator.get_be_int32();
290  _kernel_version = iterator.get_be_int32();
291  _internal_format = (InternalFormat)iterator.get_be_int32();
292  _external_format = (ExternalFormat)iterator.get_be_int32();
293  _use_mipmap_kernel = (iterator.get_be_int32() != 0);
294  int i;
295  for (i = 0; i < 8; i++) {
296  _mipmap_kernel[i] = iterator.get_be_float32();
297  }
298  _use_lod_scale = (iterator.get_be_int32() != 0);
299  for (i = 0; i < 8; i++) {
300  _lod_scale[i]._lod = iterator.get_be_float32();
301  _lod_scale[i]._scale = iterator.get_be_float32();
302  }
303  _clamp = iterator.get_be_float32();
304  _mag_filter_alpha = (Magnification)iterator.get_be_int32();
305  _mag_filter_color = (Magnification)iterator.get_be_int32();
306  iterator.skip_bytes(4 + 4 * 8);
307  _lambert_conic_central_meridian = iterator.get_be_float64();
308  _lambert_conic_upper_latitude = iterator.get_be_float64();
309  _lambert_conic_lower_latitude = iterator.get_be_float64();
310  iterator.skip_bytes(8 + 4 * 5);
311  _use_detail = (iterator.get_be_int32() != 0);
312  _detail_j = iterator.get_be_int32();
313  _detail_k = iterator.get_be_int32();
314  _detail_m = iterator.get_be_int32();
315  _detail_n = iterator.get_be_int32();
316  _detail_scramble = iterator.get_be_int32();
317  _use_tile = (iterator.get_be_int32() != 0);
318  _tile_lower_left_u = iterator.get_be_float32();
319  _tile_lower_left_v = iterator.get_be_float32();
320  _tile_upper_right_u = iterator.get_be_float32();
321  _tile_upper_right_v = iterator.get_be_float32();
322  _projection = (ProjectionType)iterator.get_be_int32();
323  _earth_model = (EarthModel)iterator.get_be_int32();
324  iterator.skip_bytes(4);
325  _utm_zone = iterator.get_be_int32();
326  _image_origin = (ImageOrigin)iterator.get_be_int32();
327  _geospecific_points_units = (PointsUnits)iterator.get_be_int32();
328  _geospecific_hemisphere = (Hemisphere)iterator.get_be_int32();
329  iterator.skip_bytes(4 + 4 + 149 * 4);
330  iterator.skip_bytes(8); // Undocumented padding.
331  _comment = iterator.get_fixed_string(512);
332 
333  if (iterator.get_remaining_size() != 0) {
334  iterator.skip_bytes(13 * 4);
335  iterator.skip_bytes(4); // Undocumented padding.
336  _file_version = iterator.get_be_int32();
337 
338  // Now read the geospecific control points.
339  _geospecific_control_points.clear();
340  int num_points = iterator.get_be_int32();
341  if (num_points > 0) {
342  iterator.skip_bytes(4);
343 
344  while (num_points > 0) {
345  GeospecificControlPoint gcp;
346  gcp._uv[0] = iterator.get_be_float64();
347  gcp._uv[1] = iterator.get_be_float64();
348  gcp._real_earth[0] = iterator.get_be_float64();
349  gcp._real_earth[1] = iterator.get_be_float64();
350  }
351  }
352 
353  if (iterator.get_remaining_size() != 0) {
354  int num_defs = iterator.get_be_int32();
355  while (num_defs > 0) {
356  SubtextureDef def;
357  def._name = iterator.get_fixed_string(32);
358  def._left = iterator.get_be_int32();
359  def._bottom = iterator.get_be_int32();
360  def._right = iterator.get_be_int32();
361  def._top = iterator.get_be_int32();
362  }
363  }
364  }
365 
366  check_remaining_size(iterator);
367  return FE_ok;
368 }
369 
370 /**
371  * Packs the attribute data into a big datagram.
372  */
373 FltError FltTexture::
374 pack_attr(Datagram &datagram) const {
375  datagram.add_be_int32(_num_texels_u);
376  datagram.add_be_int32(_num_texels_v);
377  datagram.add_be_int32(_real_world_size_u);
378  datagram.add_be_int32(_real_world_size_v);
379  datagram.add_be_int32(_up_vector_x);
380  datagram.add_be_int32(_up_vector_y);
381  datagram.add_be_int32(_file_format);
382  datagram.add_be_int32(_min_filter);
383  datagram.add_be_int32(_mag_filter);
384  datagram.add_be_int32(_repeat);
385  datagram.add_be_int32(_repeat_u);
386  datagram.add_be_int32(_repeat_v);
387  datagram.add_be_int32(_modify_flag);
388  datagram.add_be_int32(_x_pivot_point);
389  datagram.add_be_int32(_y_pivot_point);
390  datagram.add_be_int32(_env_type);
391  datagram.add_be_int32(_intensity_is_alpha);
392  datagram.pad_bytes(4 * 8);
393  datagram.pad_bytes(4); // Undocumented padding.
394  datagram.add_be_float64(_float_real_world_size_u);
395  datagram.add_be_float64(_float_real_world_size_v);
396  datagram.add_be_int32(_imported_origin_code);
397  datagram.add_be_int32(_kernel_version);
398  datagram.add_be_int32(_internal_format);
399  datagram.add_be_int32(_external_format);
400  datagram.add_be_int32(_use_mipmap_kernel);
401  int i;
402  for (i = 0; i < 8; i++) {
403  datagram.add_be_float32(_mipmap_kernel[i]);
404  }
405  datagram.add_be_int32(_use_lod_scale);
406  for (i = 0; i < 8; i++) {
407  datagram.add_be_float32(_lod_scale[i]._lod);
408  datagram.add_be_float32(_lod_scale[i]._scale);
409  }
410  datagram.add_be_float32(_clamp);
411  datagram.add_be_int32(_mag_filter_alpha);
412  datagram.add_be_int32(_mag_filter_color);
413  datagram.pad_bytes(4 + 4 * 8);
414  datagram.add_be_float64(_lambert_conic_central_meridian);
415  datagram.add_be_float64(_lambert_conic_upper_latitude);
416  datagram.add_be_float64(_lambert_conic_lower_latitude);
417  datagram.pad_bytes(8 + 4 * 5);
418  datagram.add_be_int32(_use_detail);
419  datagram.add_be_int32(_detail_j);
420  datagram.add_be_int32(_detail_k);
421  datagram.add_be_int32(_detail_m);
422  datagram.add_be_int32(_detail_n);
423  datagram.add_be_int32(_detail_scramble);
424  datagram.add_be_int32(_use_tile);
425  datagram.add_be_float32(_tile_lower_left_u);
426  datagram.add_be_float32(_tile_lower_left_v);
427  datagram.add_be_float32(_tile_upper_right_u);
428  datagram.add_be_float32(_tile_upper_right_v);
429  datagram.add_be_int32(_projection);
430  datagram.add_be_int32(_earth_model);
431  datagram.pad_bytes(4);
432  datagram.add_be_int32(_utm_zone);
433  datagram.add_be_int32(_image_origin);
434  datagram.add_be_int32(_geospecific_points_units);
435  datagram.add_be_int32(_geospecific_hemisphere);
436  datagram.pad_bytes(4 + 4 + 149 * 4);
437  datagram.pad_bytes(8); // Undocumented padding.
438  datagram.add_fixed_string(_comment, 512);
439  datagram.pad_bytes(13 * 4);
440  datagram.pad_bytes(4); // Undocumented padding.
441  datagram.add_be_int32(_file_version);
442 
443  // Now write the geospecific control points.
444  datagram.add_be_int32(_geospecific_control_points.size());
445  if (!_geospecific_control_points.empty()) {
446  datagram.pad_bytes(4);
447  GeospecificControlPoints::const_iterator pi;
448  for (pi = _geospecific_control_points.begin();
449  pi != _geospecific_control_points.end();
450  ++pi) {
451  const GeospecificControlPoint &gcp = (*pi);
452  datagram.add_be_float64(gcp._uv[0]);
453  datagram.add_be_float64(gcp._uv[1]);
454  datagram.add_be_float64(gcp._real_earth[0]);
455  datagram.add_be_float64(gcp._real_earth[1]);
456  }
457  }
458 
459  // Also write out the subtexture definitions.
460  datagram.add_be_int32(_subtexture_defs.size());
461  SubtextureDefs::const_iterator di;
462  for (di = _subtexture_defs.begin();
463  di != _subtexture_defs.end();
464  ++di) {
465  const SubtextureDef &def = (*di);
466  datagram.add_fixed_string(def._name, 31);
467  datagram.add_int8(0);
468  datagram.add_be_int32(def._left);
469  datagram.add_be_int32(def._bottom);
470  datagram.add_be_int32(def._right);
471  datagram.add_be_int32(def._top);
472  }
473 
474  return FE_ok;
475 }
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
Definition: filename.cxx:1899
This class writes a sequence of FltRecords to an ostream, handling opcode and size counts properly.
This class turns an istream into a sequence of FltRecords by reading a sequence of Datagrams and extr...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void check_remaining_size(const DatagramIterator &di, const std::string &name=std::string()) const
Checks that the iterator has no bytes left, as it should at the end of a successfully read record.
Definition: fltRecord.cxx:254
Filename get_texture_filename() const
Returns the name of the texture image file.
Definition: fltTexture.cxx:101
void set_texture_filename(const Filename &filename)
Changes the name of the texture image file.
Definition: fltTexture.cxx:109
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Definition: filename.cxx:1863
virtual void apply_converted_filenames()
Walks the hierarchy at this record and below and copies the _converted_filename record into the _orig...
Definition: fltRecord.cxx:278
DatagramIterator & get_iterator()
Returns an iterator suitable for extracting data from the current record.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void pad_bytes(size_t size)
Adds the indicated number of zero bytes to the datagram.
Definition: datagram.cxx:99
std::string to_os_generic() const
This is similar to to_os_specific(), but it is designed to generate a filename that can be understood...
Definition: filename.cxx:1182
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:44
FltError write_attr_data() const
Writes the texture's .attr file.
Definition: fltTexture.cxx:171
void add_be_float64(PN_float64 value)
Adds a 64-bit big-endian floating-point number to the datagram.
Definition: datagram.I:209
virtual void apply_converted_filenames()
Walks the hierarchy at this record and below and copies the _converted_filename record into the _orig...
Definition: fltTexture.cxx:92
void add_int8(int8_t value)
Adds a signed 8-bit integer to the datagram.
Definition: datagram.I:42
void add_be_float32(PN_float32 value)
Adds a 32-bit single-precision big-endian floating-point number to the datagram.
Definition: datagram.I:200
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The base class for all kinds of records in a MultiGen OpenFlight file.
Definition: fltRecord.h:36
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FltError read_attr_data()
Opens up the texture's .attr file and reads its data into the extra FltTexture fields.
Definition: fltTexture.cxx:136
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FltOpcode get_opcode() const
Returns the opcode associated with the current record.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A class to retrieve the individual data elements previously stored in a Datagram.
void add_fixed_string(const std::string &str, size_t size)
Adds a fixed-length string to the datagram.
Definition: datagram.I:263
void add_be_int32(int32_t value)
Adds a signed 32-bit big-endian integer to the datagram.
Definition: datagram.I:154
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Filename get_attr_filename() const
Returns the name of the texture's associated .attr file.
Definition: fltTexture.cxx:125
void set_opcode(FltOpcode opcode)
Sets the opcode associated with the current record.
Datagram & update_datagram()
Returns a modifiable reference to the datagram associated with the current record.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
Definition: datagram.I:327