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