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  */
93  _orig_filename = _converted_filename.to_os_generic();
95 }
96 
97 /**
98  * Returns the name of the texture image file.
99  */
101 get_texture_filename() const {
102  return _converted_filename;
103 }
104 
105 /**
106  * Changes the name of the texture image file.
107  */
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  */
125 get_attr_filename() const {
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::
136 read_attr_data() {
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::
171 write_attr_data() const {
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 }
A class to retrieve the individual data elements previously stored in a Datagram.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the datagram.
int32_t get_be_int32()
Extracts a signed 32-bit big-endian integer.
PN_float32 get_be_float32()
Extracts a 32-bit big-endian single-precision floating-point number.
std::string get_fixed_string(size_t size)
Extracts a fixed-length string.
PN_float64 get_be_float64()
Extracts a 64-bit big-endian floating-point number.
size_t get_remaining_size() const
Return the bytes left in the datagram.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
void add_be_int32(int32_t value)
Adds a signed 32-bit big-endian integer to the datagram.
Definition: datagram.I:154
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
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_float64(PN_float64 value)
Adds a 64-bit big-endian floating-point number to the datagram.
Definition: datagram.I:209
void pad_bytes(size_t size)
Adds the indicated number of zero bytes to the datagram.
Definition: datagram.cxx:99
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
Definition: datagram.I:327
void add_int8(int8_t value)
Adds a signed 8-bit integer to the datagram.
Definition: datagram.I:42
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Definition: filename.cxx:1863
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
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
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
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 is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:44
This class turns an istream into a sequence of FltRecords by reading a sequence of Datagrams and extr...
FltOpcode get_opcode() const
Returns the opcode associated with the current record.
DatagramIterator & get_iterator()
Returns an iterator suitable for extracting data from the current record.
This class writes a sequence of FltRecords to an ostream, handling opcode and size counts properly.
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.
The base class for all kinds of records in a MultiGen OpenFlight file.
Definition: fltRecord.h:36
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
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
FltError write_attr_data() const
Writes the texture's .attr file.
Definition: fltTexture.cxx:171
Filename get_attr_filename() const
Returns the name of the texture's associated .attr file.
Definition: fltTexture.cxx:125
FltError read_attr_data()
Opens up the texture's .attr file and reads its data into the extra FltTexture fields.
Definition: fltTexture.cxx:136
void set_texture_filename(const Filename &filename)
Changes the name of the texture image file.
Definition: fltTexture.cxx:109
Filename get_texture_filename() const
Returns the name of the texture image file.
Definition: fltTexture.cxx:101
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
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.