486 lines
17 KiB
C++
486 lines
17 KiB
C++
// Filename: fltTexture.cxx
|
|
// Created by: drose (25Aug00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "fltTexture.h"
|
|
#include "fltRecordReader.h"
|
|
#include "fltRecordWriter.h"
|
|
#include "fltHeader.h"
|
|
|
|
TypeHandle FltTexture::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
FltTexture::
|
|
FltTexture(FltHeader *header) : FltRecord(header) {
|
|
_pattern_index = 0;
|
|
_x_location = 0;
|
|
_y_location = 0;
|
|
|
|
_num_texels_u = 0;
|
|
_num_texels_v = 0;
|
|
_real_world_size_u = 0;
|
|
_real_world_size_v = 0;
|
|
_up_vector_x = 0;
|
|
_up_vector_y = 1;
|
|
_file_format = FF_none;
|
|
_min_filter = MN_point;
|
|
_mag_filter = MG_point;
|
|
_repeat = RT_repeat;
|
|
_repeat_u = RT_repeat;
|
|
_repeat_v = RT_repeat;
|
|
_modify_flag = 0;
|
|
_x_pivot_point = 0;
|
|
_y_pivot_point = 0;
|
|
_env_type = ET_modulate;
|
|
_intensity_is_alpha = false;
|
|
_float_real_world_size_u = 0.0;
|
|
_float_real_world_size_v = 0.0;
|
|
_imported_origin_code = 0;
|
|
_kernel_version = 1520;
|
|
_internal_format = IF_default;
|
|
_external_format = EF_default;
|
|
_use_mipmap_kernel = false;
|
|
memset(_mipmap_kernel, 0, sizeof(_mipmap_kernel));
|
|
_use_lod_scale = false;
|
|
memset(_lod_scale, 0, sizeof(_lod_scale));
|
|
_clamp = 0.0;
|
|
_mag_filter_alpha = MG_point;
|
|
_mag_filter_color = MG_point;
|
|
_lambert_conic_central_meridian = 0.0;
|
|
_lambert_conic_upper_latitude = 0.0;
|
|
_lambert_conic_lower_latitude = 0.0;
|
|
_use_detail = false;
|
|
_detail_j = 0;
|
|
_detail_k = 0;
|
|
_detail_m = 0;
|
|
_detail_n = 0;
|
|
_detail_scramble = 0;
|
|
_use_tile = false;
|
|
_tile_lower_left_u = 0.0;
|
|
_tile_lower_left_v = 0.0;
|
|
_tile_upper_right_u = 0.0;
|
|
_tile_upper_right_v = 0.0;
|
|
_projection = PT_flat_earth;
|
|
_earth_model = EM_wgs84;
|
|
_utm_zone = 0;
|
|
_image_origin = IO_lower_left;
|
|
_geospecific_points_units = PU_degrees;
|
|
_geospecific_hemisphere = H_southern;
|
|
_file_version = 1501;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::get_texture_filename
|
|
// Access: Public
|
|
// Description: Returns the name of the texture image file. If it
|
|
// appears to be a relative filename, it will be
|
|
// converted to the correct full pathname according to
|
|
// the texture_path specified in the header.
|
|
////////////////////////////////////////////////////////////////////
|
|
Filename FltTexture::
|
|
get_texture_filename() const {
|
|
Filename file(_filename);
|
|
file.resolve_filename(_header->get_texture_path());
|
|
return file;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::get_attr_filename
|
|
// Access: Public
|
|
// Description: Returns the name of the texture's associated .attr
|
|
// file. This contains some additional MultiGen
|
|
// information about the texture parameters. This is,
|
|
// of course, just the name of the texture with .attr
|
|
// appended.
|
|
//
|
|
// Normally, it won't be necessary to access this file
|
|
// directly; you can call read_attr_data() or
|
|
// write_attr_data() to get at the data stored in this
|
|
// file. (And read_attr_data() is called automatically
|
|
// when the Flt file is read in.)
|
|
////////////////////////////////////////////////////////////////////
|
|
Filename FltTexture::
|
|
get_attr_filename() const {
|
|
string texture_filename = get_texture_filename();
|
|
return Filename::binary_filename(texture_filename + ".attr");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::read_attr_data
|
|
// Access: Public
|
|
// Description: Opens up the texture's .attr file and reads its data
|
|
// into the extra FltTexture fields. This is normally
|
|
// performed automatically when the Flt file is read
|
|
// from disk.
|
|
////////////////////////////////////////////////////////////////////
|
|
FltError FltTexture::
|
|
read_attr_data() {
|
|
Filename attr_filename = get_attr_filename();
|
|
|
|
ifstream attr;
|
|
if (!attr_filename.open_read(attr)) {
|
|
return FE_could_not_open;
|
|
}
|
|
|
|
// Determine the file's size so we can read it all into one big
|
|
// datagram.
|
|
attr.seekg(0, ios::end);
|
|
if (attr.fail()) {
|
|
return FE_read_error;
|
|
}
|
|
streampos length = attr.tellg();
|
|
|
|
char *buffer = new char[length];
|
|
|
|
attr.seekg(0, ios::beg);
|
|
attr.read(buffer, length);
|
|
if (attr.fail()) {
|
|
return FE_read_error;
|
|
}
|
|
|
|
Datagram datagram(buffer, length);
|
|
delete[] buffer;
|
|
|
|
return unpack_attr(datagram);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::write_attr_data
|
|
// Access: Public
|
|
// Description: Writes the texture's .attr file. This may or may
|
|
// not be performed automatically, according to the
|
|
// setting of FltHeader::set_auto_attr_update().
|
|
////////////////////////////////////////////////////////////////////
|
|
FltError FltTexture::
|
|
write_attr_data() const {
|
|
return write_attr_data(get_attr_filename());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::write_attr_data
|
|
// Access: Public
|
|
// Description: Writes the texture's .attr file to the named
|
|
// file.
|
|
////////////////////////////////////////////////////////////////////
|
|
FltError FltTexture::
|
|
write_attr_data(Filename attr_filename) const {
|
|
Datagram datagram;
|
|
FltError result = pack_attr(datagram);
|
|
if (result != FE_ok) {
|
|
return result;
|
|
}
|
|
|
|
attr_filename.set_binary();
|
|
ofstream attr;
|
|
if (!attr_filename.open_write(attr)) {
|
|
return FE_could_not_open;
|
|
}
|
|
|
|
attr.write((const char *)datagram.get_data(), datagram.get_length());
|
|
if (attr.fail()) {
|
|
return FE_write_error;
|
|
}
|
|
return FE_ok;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::extract_record
|
|
// Access: Protected, Virtual
|
|
// Description: Fills in the information in this record based on the
|
|
// information given in the indicated datagram, whose
|
|
// opcode has already been read. Returns true on
|
|
// success, false if the datagram is invalid.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool FltTexture::
|
|
extract_record(FltRecordReader &reader) {
|
|
if (!FltRecord::extract_record(reader)) {
|
|
return false;
|
|
}
|
|
|
|
nassertr(reader.get_opcode() == FO_texture, false);
|
|
DatagramIterator &iterator = reader.get_iterator();
|
|
|
|
_filename = iterator.get_fixed_string(200);
|
|
_pattern_index = iterator.get_be_int32();
|
|
_x_location = iterator.get_be_int32();
|
|
_y_location = iterator.get_be_int32();
|
|
|
|
if (read_attr_data() != FE_ok) {
|
|
nout << "Unable to read attribute file " << get_attr_filename() << "\n";
|
|
}
|
|
|
|
check_remaining_size(iterator);
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::build_record
|
|
// Access: Protected, Virtual
|
|
// Description: Fills up the current record on the FltRecordWriter with
|
|
// data for this record, but does not advance the
|
|
// writer. Returns true on success, false if there is
|
|
// some error.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool FltTexture::
|
|
build_record(FltRecordWriter &writer) const {
|
|
if (!FltRecord::build_record(writer)) {
|
|
return false;
|
|
}
|
|
|
|
writer.set_opcode(FO_texture);
|
|
Datagram &datagram = writer.update_datagram();
|
|
|
|
datagram.add_fixed_string(_filename, 200);
|
|
datagram.add_be_int32(_pattern_index);
|
|
datagram.add_be_int32(_x_location);
|
|
datagram.add_be_int32(_y_location);
|
|
|
|
if (_header->get_auto_attr_update() == FltHeader::AU_always ||
|
|
(_header->get_auto_attr_update() == FltHeader::AU_if_missing &&
|
|
!get_attr_filename().exists())) {
|
|
if (write_attr_data() != FE_ok) {
|
|
nout << "Unable to write attribute file " << get_attr_filename() << "\n";
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::unpack_attr
|
|
// Access: Private
|
|
// Description: Reads the data from the attribute file.
|
|
////////////////////////////////////////////////////////////////////
|
|
FltError FltTexture::
|
|
unpack_attr(const Datagram &datagram) {
|
|
DatagramIterator iterator(datagram);
|
|
|
|
_num_texels_u = iterator.get_be_int32();
|
|
_num_texels_v = iterator.get_be_int32();
|
|
_real_world_size_u = iterator.get_be_int32();
|
|
_real_world_size_v = iterator.get_be_int32();
|
|
_up_vector_x = iterator.get_be_int32();
|
|
_up_vector_y = iterator.get_be_int32();
|
|
_file_format = (FileFormat)iterator.get_be_int32();
|
|
_min_filter = (Minification)iterator.get_be_int32();
|
|
_mag_filter = (Magnification)iterator.get_be_int32();
|
|
_repeat = (RepeatType)iterator.get_be_int32();
|
|
_repeat_u = (RepeatType)iterator.get_be_int32();
|
|
_repeat_v = (RepeatType)iterator.get_be_int32();
|
|
_modify_flag = iterator.get_be_int32();
|
|
_x_pivot_point = iterator.get_be_int32();
|
|
_y_pivot_point = iterator.get_be_int32();
|
|
_env_type = (EnvironmentType)iterator.get_be_int32();
|
|
_intensity_is_alpha = (iterator.get_be_int32() != 0);
|
|
iterator.skip_bytes(4 * 8);
|
|
iterator.skip_bytes(4); // Undocumented padding.
|
|
_float_real_world_size_u = iterator.get_be_float64();
|
|
_float_real_world_size_v = iterator.get_be_float64();
|
|
_imported_origin_code = iterator.get_be_int32();
|
|
_kernel_version = iterator.get_be_int32();
|
|
_internal_format = (InternalFormat)iterator.get_be_int32();
|
|
_external_format = (ExternalFormat)iterator.get_be_int32();
|
|
_use_mipmap_kernel = (iterator.get_be_int32() != 0);
|
|
int i;
|
|
for (i = 0; i < 8; i++) {
|
|
_mipmap_kernel[i] = iterator.get_be_float32();
|
|
}
|
|
_use_lod_scale = (iterator.get_be_int32() != 0);
|
|
for (i = 0; i < 8; i++) {
|
|
_lod_scale[i]._lod = iterator.get_be_float32();
|
|
_lod_scale[i]._scale = iterator.get_be_float32();
|
|
}
|
|
_clamp = iterator.get_be_float32();
|
|
_mag_filter_alpha = (Magnification)iterator.get_be_int32();
|
|
_mag_filter_color = (Magnification)iterator.get_be_int32();
|
|
iterator.skip_bytes(4 + 4 * 8);
|
|
_lambert_conic_central_meridian = iterator.get_be_float64();
|
|
_lambert_conic_upper_latitude = iterator.get_be_float64();
|
|
_lambert_conic_lower_latitude = iterator.get_be_float64();
|
|
iterator.skip_bytes(8 + 4 * 5);
|
|
_use_detail = (iterator.get_be_int32() != 0);
|
|
_detail_j = iterator.get_be_int32();
|
|
_detail_k = iterator.get_be_int32();
|
|
_detail_m = iterator.get_be_int32();
|
|
_detail_n = iterator.get_be_int32();
|
|
_detail_scramble = iterator.get_be_int32();
|
|
_use_tile = (iterator.get_be_int32() != 0);
|
|
_tile_lower_left_u = iterator.get_be_float32();
|
|
_tile_lower_left_v = iterator.get_be_float32();
|
|
_tile_upper_right_u = iterator.get_be_float32();
|
|
_tile_upper_right_v = iterator.get_be_float32();
|
|
_projection = (ProjectionType)iterator.get_be_int32();
|
|
_earth_model = (EarthModel)iterator.get_be_int32();
|
|
iterator.skip_bytes(4);
|
|
_utm_zone = iterator.get_be_int32();
|
|
_image_origin = (ImageOrigin)iterator.get_be_int32();
|
|
_geospecific_points_units = (PointsUnits)iterator.get_be_int32();
|
|
_geospecific_hemisphere = (Hemisphere)iterator.get_be_int32();
|
|
iterator.skip_bytes(4 + 4 + 149 * 4);
|
|
iterator.skip_bytes(8); // Undocumented padding.
|
|
_comment = iterator.get_fixed_string(512);
|
|
|
|
if (iterator.get_remaining_size() != 0) {
|
|
iterator.skip_bytes(13 * 4);
|
|
iterator.skip_bytes(4); // Undocumented padding.
|
|
_file_version = iterator.get_be_int32();
|
|
|
|
// Now read the geospecific control points.
|
|
_geospecific_control_points.clear();
|
|
int num_points = iterator.get_be_int32();
|
|
if (num_points > 0) {
|
|
iterator.skip_bytes(4);
|
|
|
|
while (num_points > 0) {
|
|
GeospecificControlPoint gcp;
|
|
gcp._uv[0] = iterator.get_be_float64();
|
|
gcp._uv[1] = iterator.get_be_float64();
|
|
gcp._real_earth[0] = iterator.get_be_float64();
|
|
gcp._real_earth[1] = iterator.get_be_float64();
|
|
}
|
|
}
|
|
|
|
if (iterator.get_remaining_size() != 0) {
|
|
int num_defs = iterator.get_be_int32();
|
|
while (num_defs > 0) {
|
|
SubtextureDef def;
|
|
def._name = iterator.get_fixed_string(32);
|
|
def._left = iterator.get_be_int32();
|
|
def._bottom = iterator.get_be_int32();
|
|
def._right = iterator.get_be_int32();
|
|
def._top = iterator.get_be_int32();
|
|
}
|
|
}
|
|
}
|
|
|
|
check_remaining_size(iterator);
|
|
return FE_ok;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltTexture::pack_attr
|
|
// Access: Private
|
|
// Description: Packs the attribute data into a big datagram.
|
|
////////////////////////////////////////////////////////////////////
|
|
FltError FltTexture::
|
|
pack_attr(Datagram &datagram) const {
|
|
datagram.add_be_int32(_num_texels_u);
|
|
datagram.add_be_int32(_num_texels_v);
|
|
datagram.add_be_int32(_real_world_size_u);
|
|
datagram.add_be_int32(_real_world_size_v);
|
|
datagram.add_be_int32(_up_vector_x);
|
|
datagram.add_be_int32(_up_vector_y);
|
|
datagram.add_be_int32(_file_format);
|
|
datagram.add_be_int32(_min_filter);
|
|
datagram.add_be_int32(_mag_filter);
|
|
datagram.add_be_int32(_repeat);
|
|
datagram.add_be_int32(_repeat_u);
|
|
datagram.add_be_int32(_repeat_v);
|
|
datagram.add_be_int32(_modify_flag);
|
|
datagram.add_be_int32(_x_pivot_point);
|
|
datagram.add_be_int32(_y_pivot_point);
|
|
datagram.add_be_int32(_env_type);
|
|
datagram.add_be_int32(_intensity_is_alpha);
|
|
datagram.pad_bytes(4 * 8);
|
|
datagram.pad_bytes(4); // Undocumented padding.
|
|
datagram.add_be_float64(_float_real_world_size_u);
|
|
datagram.add_be_float64(_float_real_world_size_v);
|
|
datagram.add_be_int32(_imported_origin_code);
|
|
datagram.add_be_int32(_kernel_version);
|
|
datagram.add_be_int32(_internal_format);
|
|
datagram.add_be_int32(_external_format);
|
|
datagram.add_be_int32(_use_mipmap_kernel);
|
|
int i;
|
|
for (i = 0; i < 8; i++) {
|
|
datagram.add_be_float32(_mipmap_kernel[i]);
|
|
}
|
|
datagram.add_be_int32(_use_lod_scale);
|
|
for (i = 0; i < 8; i++) {
|
|
datagram.add_be_float32(_lod_scale[i]._lod);
|
|
datagram.add_be_float32(_lod_scale[i]._scale);
|
|
}
|
|
datagram.add_be_float32(_clamp);
|
|
datagram.add_be_int32(_mag_filter_alpha);
|
|
datagram.add_be_int32(_mag_filter_color);
|
|
datagram.pad_bytes(4 + 4 * 8);
|
|
datagram.add_be_float64(_lambert_conic_central_meridian);
|
|
datagram.add_be_float64(_lambert_conic_upper_latitude);
|
|
datagram.add_be_float64(_lambert_conic_lower_latitude);
|
|
datagram.pad_bytes(8 + 4 * 5);
|
|
datagram.add_be_int32(_use_detail);
|
|
datagram.add_be_int32(_detail_j);
|
|
datagram.add_be_int32(_detail_k);
|
|
datagram.add_be_int32(_detail_m);
|
|
datagram.add_be_int32(_detail_n);
|
|
datagram.add_be_int32(_detail_scramble);
|
|
datagram.add_be_int32(_use_tile);
|
|
datagram.add_be_float32(_tile_lower_left_u);
|
|
datagram.add_be_float32(_tile_lower_left_v);
|
|
datagram.add_be_float32(_tile_upper_right_u);
|
|
datagram.add_be_float32(_tile_upper_right_v);
|
|
datagram.add_be_int32(_projection);
|
|
datagram.add_be_int32(_earth_model);
|
|
datagram.pad_bytes(4);
|
|
datagram.add_be_int32(_utm_zone);
|
|
datagram.add_be_int32(_image_origin);
|
|
datagram.add_be_int32(_geospecific_points_units);
|
|
datagram.add_be_int32(_geospecific_hemisphere);
|
|
datagram.pad_bytes(4 + 4 + 149 * 4);
|
|
datagram.pad_bytes(8); // Undocumented padding.
|
|
datagram.add_fixed_string(_comment, 512);
|
|
datagram.pad_bytes(13 * 4);
|
|
datagram.pad_bytes(4); // Undocumented padding.
|
|
datagram.add_be_int32(_file_version);
|
|
|
|
// Now write the geospecific control points.
|
|
datagram.add_be_int32(_geospecific_control_points.size());
|
|
if (!_geospecific_control_points.empty()) {
|
|
datagram.pad_bytes(4);
|
|
GeospecificControlPoints::const_iterator pi;
|
|
for (pi = _geospecific_control_points.begin();
|
|
pi != _geospecific_control_points.end();
|
|
++pi) {
|
|
const GeospecificControlPoint &gcp = (*pi);
|
|
datagram.add_be_float64(gcp._uv[0]);
|
|
datagram.add_be_float64(gcp._uv[1]);
|
|
datagram.add_be_float64(gcp._real_earth[0]);
|
|
datagram.add_be_float64(gcp._real_earth[1]);
|
|
}
|
|
}
|
|
|
|
// Also write out the subtexture definitions.
|
|
datagram.add_be_int32(_subtexture_defs.size());
|
|
SubtextureDefs::const_iterator di;
|
|
for (di = _subtexture_defs.begin();
|
|
di != _subtexture_defs.end();
|
|
++di) {
|
|
const SubtextureDef &def = (*di);
|
|
datagram.add_fixed_string(def._name, 31);
|
|
datagram.add_int8(0);
|
|
datagram.add_be_int32(def._left);
|
|
datagram.add_be_int32(def._bottom);
|
|
datagram.add_be_int32(def._right);
|
|
datagram.add_be_int32(def._top);
|
|
}
|
|
|
|
return FE_ok;
|
|
}
|