extend ModelNode::preserve_transform and Texture::alpha_file_channel

This commit is contained in:
David Rose 2003-04-15 22:35:07 +00:00
parent a7967b955c
commit df2a60cfb0
22 changed files with 391 additions and 148 deletions

View File

@ -761,26 +761,30 @@ GROUPING ENTRIES
<DCS> { boolean-value }
This indicates that this group contains geometry that might need
to be repositioned interactively relative to the rest of the
scene. The egg loader interprets this by creating a pfDCS node
instead of a pfGroup node. This also implies <Model>, below.
DCS stands for Dynamic Coordinate System. This indicates that
show code will expect to be able to read the transform set on this
node at run time, and may need to modify the transform further.
This is a special case of <Model>, below.
<TexList> { boolean-value }
<DCS> { dcs-type }
This indicates that this group contains geometry whose textures
might need to be separately managed. A special xpfTexListNode is
created for this group. This also implies <Model>.
This is another syntax for the <DCS> flag. The dcs-type string
should be one of either "local" or "net", which specifies the kind
of preserve_transform flag that will be set on the corresponding
ModelNode. If the string is "local", it indicates that the local
transform on this node (as well as the net transform) will not be
affected by any flattening operation and will be preserved through
the entire model loading process. If the string is "net", then
only the net transform will be preserved; the local transform may
be adjusted in the event of a flatten operation.
<Model> { boolean-value }
This indicates that the show code might need a pointer to this
particular group. If any nodes in the egg file have the <Model>
flag set, the egg loader creates an xpfModelRoot node as the root
node of the file, which keeps a short list of all the nodes with
the <Model> flag set. This allows quick access to these nodes by
the show code at run time. In the old player this also implied
<DCS>, but it doesn't any more.
particular group. This creates a ModelNode at the corresponding
level, which is guaranteed not to be removed by any flatten
operation. However, its transform might still be changed, but see
also the <DCS> flag, above.
<Dart> { boolean-value }

View File

@ -165,7 +165,16 @@ read(istream &in) {
////////////////////////////////////////////////////////////////////
void EggData::
merge(EggData &other) {
other.set_coordinate_system(get_coordinate_system());
if (get_coordinate_system() == CS_default) {
// If we haven't specified a coordinate system yet, we inherit the
// other one's.
set_coordinate_system(other.get_coordinate_system());
} else {
// Otherwise, the other one is forced into our coordinate system
// before we merge.
other.set_coordinate_system(get_coordinate_system());
}
steal_children(other);
}

View File

@ -217,27 +217,25 @@ get_collide_flags() const {
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::set_dcs_flag
// Function: EggGroup::set_dcs_type
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void EggGroup::
set_dcs_flag(bool flag) {
if (flag) {
_flags |= F_dcs_flag;
} else {
_flags &= ~F_dcs_flag;
}
set_dcs_type(EggGroup::DCSType type) {
// Make sure the user didn't give us any stray bits.
nassertv((type & ~F2_dcs_type)==0);
_flags2 = (_flags2 & ~F2_dcs_type) | type;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::get_dcs_flag
// Function: EggGroup::get_dcs_type
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool EggGroup::
get_dcs_flag() const {
return ((_flags & F_dcs_flag) != 0);
INLINE EggGroup::DCSType EggGroup::
get_dcs_type() const {
return (DCSType)(_flags2 & F2_dcs_type);
}
////////////////////////////////////////////////////////////////////
@ -246,7 +244,7 @@ get_dcs_flag() const {
// Description:
////////////////////////////////////////////////////////////////////
INLINE void EggGroup::
set_dart_type(DartType type) {
set_dart_type(EggGroup::DartType type) {
// Make sure the user didn't give us any stray bits.
nassertv((type & ~F_dart_type)==0);
_flags = (_flags & ~F_dart_type) | type;

View File

@ -236,8 +236,9 @@ write(ostream &out, int indent_level) const {
out << " }\n";
}
if (get_dcs_flag()) {
indent(out, indent_level + 2) << "<DCS> { 1 }\n";
if (get_dcs_type() != DC_none) {
indent(out, indent_level + 2)
<< "<DCS> { " << get_dcs_type() << " }\n";
}
if (get_dart_type() != DT_none) {
@ -542,6 +543,26 @@ string_dart_type(const string &string) {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::string_dcs_type
// Access: Public, Static
// Description: Returns the DCSType value associated with the given
// string representation, or DC_none if the string
// does not match any known DCSType value.
////////////////////////////////////////////////////////////////////
EggGroup::DCSType EggGroup::
string_dcs_type(const string &string) {
if (cmp_nocase_uh(string, "local") == 0) {
return DC_local;
} else if (cmp_nocase_uh(string, "net") == 0) {
return DC_net;
} else if (cmp_nocase_uh(string, "default") == 0) {
return DC_default;
} else {
return DC_none;
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::string_billboard_type
// Access: Public, Static
@ -897,6 +918,26 @@ ostream &operator << (ostream &out, EggGroup::DartType t) {
return out << "(**invalid**)";
}
////////////////////////////////////////////////////////////////////
// Function: DCSType output operator
// Description:
////////////////////////////////////////////////////////////////////
ostream &operator << (ostream &out, EggGroup::DCSType t) {
switch (t) {
case EggGroup::DC_none:
return out << "none";
case EggGroup::DC_local:
return out << "local";
case EggGroup::DC_net:
return out << "net";
case EggGroup::DC_default:
return out << "1";
}
nassertr(false, out);
return out << "(**invalid**)";
}
////////////////////////////////////////////////////////////////////
// Function: BillboardType output operator
// Description:

View File

@ -56,6 +56,13 @@ public:
DT_nosync = 0x00000008,
DT_default = 0x0000000c,
};
enum DCSType {
// The bits here must correspond to those in Flags2, below.
DC_none = 0x00000000,
DC_local = 0x00000010,
DC_net = 0x00000020,
DC_default = 0x00000030,
};
enum BillboardType {
// The bits here must correspond to those in Flags, below.
BT_none = 0x00000000,
@ -121,8 +128,8 @@ public:
INLINE bool has_collision_name() const;
INLINE const string &get_collision_name() const;
INLINE void set_dcs_flag(bool flag);
INLINE bool get_dcs_flag() const;
INLINE void set_dcs_type(DCSType type);
INLINE DCSType get_dcs_type() const;
INLINE void set_dart_type(DartType type);
INLINE DartType get_dart_type() const;
@ -192,6 +199,7 @@ public:
static GroupType string_group_type(const string &string);
static DartType string_dart_type(const string &string);
static DCSType string_dcs_type(const string &string);
static BillboardType string_billboard_type(const string &string);
static CollisionSolidType string_cs_type(const string &string);
static CollideFlags string_collide_flags(const string &string);
@ -211,7 +219,7 @@ private:
enum Flags {
F_group_type = 0x00000003,
F_dart_type = 0x0000000c,
F_dcs_flag = 0x00000010,
F_billboard_type = 0x000000e0,
F_switch_flag = 0x00000100,
F_model_flag = 0x00000400,
@ -227,6 +235,8 @@ private:
F2_from_collide_mask = 0x00000002,
F2_into_collide_mask = 0x00000004,
F2_billboard_center = 0x00000008,
F2_dcs_type = 0x00000030,
};
int _flags;
@ -263,6 +273,7 @@ private:
ostream &operator << (ostream &out, EggGroup::GroupType t);
ostream &operator << (ostream &out, EggGroup::DartType t);
ostream &operator << (ostream &out, EggGroup::DCSType t);
ostream &operator << (ostream &out, EggGroup::BillboardType t);
ostream &operator << (ostream &out, EggGroup::CollisionSolidType t);
ostream &operator << (ostream &out, EggGroup::CollideFlags t);

View File

@ -206,15 +206,13 @@ has_anisotropic_degree() const {
// Function: EggTexture::get_anisotropic_degree
// Access: Public
// Description: Returns the anisotropic filtering degree that has
// been specified for this texture. It is an error to
// call this unless has_anisotropic_degree() returns
// true.
// been specified for this texture, or 0 if nothing has
// been specified.
////////////////////////////////////////////////////////////////////
INLINE int EggTexture::
get_anisotropic_degree() const {
// nassertr(has_anisotropic_degree(), 1);
// note: _anisotropic_degree's of 0 and 1 are equivalent (no anisotropic filtering to be done by gsg)
// note: _anisotropic_degree of 0 and 1 are equivalent (no
// anisotropic filtering to be done by gsg)
return _anisotropic_degree;
}
@ -382,6 +380,60 @@ set_alpha_fullpath(const Filename &alpha_fullpath) {
_alpha_fullpath = alpha_fullpath;
}
////////////////////////////////////////////////////////////////////
// Function: EggTexture::set_alpha_file_channel
// Access: Public
// Description: If a separate alpha-file is specified, this indicates
// which channel number should be extracted from this
// file to derive the alpha channel for the final image.
// The default is 0, which means the grayscale
// combination of r, g, b. Otherwise, this should be
// the 1-based channel number, for instance 1, 2, or 3
// for r, g, or b, respectively, or 4 for the alpha
// channel of a four-component image.
////////////////////////////////////////////////////////////////////
INLINE void EggTexture::
set_alpha_file_channel(int alpha_file_channel) {
_alpha_file_channel = alpha_file_channel;
_flags |= F_has_alpha_file_channel;
}
////////////////////////////////////////////////////////////////////
// Function: EggTexture::clear_alpha_file_channel
// Access: Public
// Description: Removes the specification of a particular channel to
// use from the alpha-file image.
////////////////////////////////////////////////////////////////////
INLINE void EggTexture::
clear_alpha_file_channel() {
_alpha_file_channel = 0;
_flags &= ~F_has_alpha_file_channel;
}
////////////////////////////////////////////////////////////////////
// Function: EggTexture::has_alpha_file_channel
// Access: Public
// Description: Returns true if a particular channel has been
// specified for the alpha-file image, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool EggTexture::
has_alpha_file_channel() const {
return (_flags & F_has_alpha_file_channel) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: EggTexture::get_alpha_file_channel
// Access: Public
// Description: Returns the particular channel that has been
// specified for the alpha-file image, or 0 if no
// channel has been specified. See
// set_alpha_file_channel().
////////////////////////////////////////////////////////////////////
INLINE int EggTexture::
get_alpha_file_channel() const {
return _alpha_file_channel;
}
////////////////////////////////////////////////////////////////////
// Function: UniqueEggTextures::Constructor
// Access: Public

View File

@ -45,6 +45,7 @@ EggTexture(const string &tref_name, const string &filename)
_env_type = ET_unspecified;
_flags = 0;
_transform = LMatrix3d::ident_mat();
_alpha_file_channel = 0;
}
////////////////////////////////////////////////////////////////////
@ -79,6 +80,7 @@ operator = (const EggTexture &copy) {
_transform = copy._transform;
_alpha_filename = copy._alpha_filename;
_alpha_fullpath = copy._alpha_fullpath;
_alpha_file_channel = copy._alpha_file_channel;
return *this;
}
@ -101,6 +103,12 @@ write(ostream &out, int indent_level) const {
out << " }\n";
}
if (has_alpha_file_channel()) {
indent(out, indent_level + 2)
<< "<Scalar> alpha-file-channel { "
<< get_alpha_file_channel() << " }\n";
}
if (get_format() != F_unspecified) {
indent(out, indent_level + 2)
<< "<Scalar> format { " << get_format() << " }\n";

View File

@ -128,6 +128,11 @@ public:
INLINE void set_alpha_fullpath(const Filename &fullpath);
INLINE const Filename &get_alpha_fullpath() const;
INLINE void set_alpha_file_channel(int alpha_file_channel);
INLINE void clear_alpha_file_channel();
INLINE bool has_alpha_file_channel() const;
INLINE int get_alpha_file_channel() const;
static Format string_format(const string &string);
static WrapMode string_wrap_mode(const string &string);
static FilterType string_filter_type(const string &string);
@ -141,6 +146,7 @@ private:
F_has_transform = 0x0001,
F_has_alpha_filename = 0x0002,
F_has_anisotropic_degree = 0x0004,
F_has_alpha_file_channel = 0x0008,
};
Format _format;
@ -152,6 +158,7 @@ private:
LMatrix3d _transform;
Filename _alpha_filename;
Filename _alpha_fullpath;
int _alpha_file_channel;
public:

View File

@ -397,6 +397,9 @@ texture_body:
} else if (cmp_nocase_uh(name, "alpha_file") == 0) {
texture->set_alpha_filename(strval);
} else if (cmp_nocase_uh(name, "alpha_file_channel") == 0) {
texture->set_alpha_file_channel((int)value);
} else {
eggyywarning("Unsupported texture scalar: " + name);
}
@ -940,7 +943,20 @@ group_body:
{
EggGroup *group = DCAST(EggGroup, egg_stack.back());
int value = (int)$4;
group->set_dcs_flag(value!=0);
group->set_dcs_type(value!=0 ? EggGroup::DC_default : EggGroup::DC_none);
}
| group_body DCS '{' STRING '}'
{
// The special flavor of DCS, with { sync } or { nosync }.
EggGroup *group = DCAST(EggGroup, egg_stack.back());
string strval = $4;
EggGroup::DCSType f = EggGroup::string_dcs_type(strval);
if (f == EggGroup::DC_none) {
eggyywarning("Unknown DCS type " + strval);
} else {
group->set_dcs_type(f);
}
}
| group_body DART '{' integer '}'
{

View File

@ -185,7 +185,7 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part) {
index = _parts.size();
_parts.push_back(joint);
if (egg_group->get_dcs_flag()) {
if (egg_group->get_dcs_type() != EggGroup::DC_none) {
// If the joint requested an explicit DCS, create a node for
// it.
joint->_geom_node = new PandaNode(egg_group->get_name());
@ -375,7 +375,7 @@ determine_primitive_home(EggPrimitive *egg_primitive) {
if (egg_group != (EggGroup *)NULL &&
egg_group->get_group_type() == EggGroup::GT_joint &&
!egg_group->get_dcs_flag()) {
egg_group->get_dcs_type() == EggGroup::DC_none) {
// If the home is a joint without a <DCS> flag--this is the normal
// case--we'll move the polygon under the character node and
// animate it from there explicitly.

View File

@ -476,21 +476,24 @@ load_textures() {
////////////////////////////////////////////////////////////////////
bool EggLoader::
load_texture(TextureDef &def, const EggTexture *egg_tex) {
// Check to see if we should reduce the number of components in
// Check to see if we should reduce the number of channels in
// the texture.
int wanted_components = 0;
int wanted_channels = 0;
bool wanted_alpha = false;
switch (egg_tex->get_format()) {
case EggTexture::F_red:
case EggTexture::F_green:
case EggTexture::F_blue:
case EggTexture::F_alpha:
case EggTexture::F_luminance:
wanted_components = 1;
wanted_channels = 1;
wanted_alpha = false;
break;
case EggTexture::F_luminance_alpha:
case EggTexture::F_luminance_alphamask:
wanted_components = 2;
wanted_channels = 2;
wanted_alpha = true;
break;
case EggTexture::F_rgb:
@ -498,7 +501,8 @@ load_texture(TextureDef &def, const EggTexture *egg_tex) {
case EggTexture::F_rgb8:
case EggTexture::F_rgb5:
case EggTexture::F_rgb332:
wanted_components = 3;
wanted_channels = 3;
wanted_alpha = false;
break;
case EggTexture::F_rgba:
@ -507,7 +511,8 @@ load_texture(TextureDef &def, const EggTexture *egg_tex) {
case EggTexture::F_rgba8:
case EggTexture::F_rgba4:
case EggTexture::F_rgba5:
wanted_components = 4;
wanted_channels = 4;
wanted_alpha = true;
break;
case EggTexture::F_unspecified:
@ -515,13 +520,14 @@ load_texture(TextureDef &def, const EggTexture *egg_tex) {
}
Texture *tex;
if (egg_tex->has_alpha_filename()) {
if (egg_tex->has_alpha_filename() && wanted_alpha) {
tex = TexturePool::load_texture(egg_tex->get_fullpath(),
egg_tex->get_alpha_fullpath(),
wanted_components);
wanted_channels,
egg_tex->get_alpha_file_channel());
} else {
tex = TexturePool::load_texture(egg_tex->get_fullpath(),
wanted_components);
wanted_channels);
}
if (tex == (Texture *)NULL) {
return false;
@ -531,7 +537,7 @@ load_texture(TextureDef &def, const EggTexture *egg_tex) {
// egg file). These filenames will be written back to the bam file
// if the bam file is written out.
tex->set_filename(egg_tex->get_filename());
if (egg_tex->has_alpha_filename()) {
if (egg_tex->has_alpha_filename() && wanted_alpha) {
tex->set_alpha_filename(egg_tex->get_alpha_filename());
}
@ -1373,10 +1379,23 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
make_node(*ci, node);
}
} else if (egg_group->get_model_flag() || egg_group->get_dcs_flag()) {
} else if (egg_group->get_model_flag() ||
egg_group->get_dcs_type() != EggGroup::DC_none) {
// A model or DCS flag; create a model node.
node = new ModelNode(egg_group->get_name());
DCAST(ModelNode, node)->set_preserve_transform(egg_group->get_dcs_flag());
switch (egg_group->get_dcs_type()) {
case EggGroup::DC_net:
DCAST(ModelNode, node)->set_preserve_transform(ModelNode::PT_net);
break;
case EggGroup::DC_local:
case EggGroup::DC_default:
DCAST(ModelNode, node)->set_preserve_transform(ModelNode::PT_local);
break;
case EggGroup::DC_none:
break;
}
EggGroup::const_iterator ci;
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {

View File

@ -16,23 +16,37 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include "pandabase.h"
#include "imageBuffer.h"
#include "config_gobj.h"
#include "config_util.h"
#include <datagram.h>
#include <datagramIterator.h>
#include <bamReader.h>
#include "datagram.h"
#include "datagramIterator.h"
#include "bamReader.h"
TypeHandle ImageBuffer::_type_handle;
////////////////////////////////////////////////////////////////////
// Static variables
// Function: ImageBuffer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
TypeHandle ImageBuffer::_type_handle;
ImageBuffer::
ImageBuffer() {
_primary_file_num_channels = 0;
_alpha_file_channel = 0;
}
////////////////////////////////////////////////////////////////////
// Function: ImageBuffer::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
ImageBuffer::
~ImageBuffer() {
}
////////////////////////////////////////////////////////////////////
// Function: ImageBuffer::write_datagram
@ -85,6 +99,8 @@ write_datagram(BamWriter *, Datagram &me)
me.add_string(get_name());
me.add_string(filename);
me.add_string(alpha_filename);
me.add_uint8(_primary_file_num_channels);
me.add_uint8(_alpha_file_channel);
}
////////////////////////////////////////////////////////////////////
@ -100,4 +116,12 @@ fillin(DatagramIterator &scan, BamReader *manager) {
set_name(scan.get_string());
set_filename(scan.get_string());
set_alpha_filename(scan.get_string());
if (manager->get_file_minor_ver() < 3) {
_primary_file_num_channels = 0;
_alpha_file_channel = 0;
} else {
_primary_file_num_channels = scan.get_uint8();
_alpha_file_channel = scan.get_uint8();
}
}

View File

@ -27,10 +27,6 @@
#include "filename.h"
#include "namable.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
class RenderBuffer;
class DisplayRegion;
@ -41,8 +37,8 @@ class DisplayRegion;
class EXPCL_PANDA ImageBuffer : public ReferenceCount,
public WritableConfigurable, public Namable {
PUBLISHED:
ImageBuffer() { }
virtual ~ImageBuffer() { }
ImageBuffer();
virtual ~ImageBuffer();
public:
virtual void config( void ) { WritableConfigurable::config(); }
@ -79,12 +75,24 @@ private:
Filename _fullpath;
Filename _alpha_fullpath;
protected:
// These are set by (and read by) the derived Texture class.
// The number of channels of the primary file we use. 1, 2, 3, or 4.
int _primary_file_num_channels;
// If we have a separate alpha file, this designates which channel
// in the alpha file provides the alpha channel. 0 indicates the
// combined grayscale value of rgb; otherwise, 1, 2, 3, or 4 are
// valid.
int _alpha_file_channel;
public:
//Abstract class, so no factory methods for Reading and Writing
virtual void write_datagram(BamWriter* manager, Datagram &me);
// Abstract class, so no factory methods for Reading and Writing
virtual void write_datagram(BamWriter *manager, Datagram &me);
protected:
void fillin(DatagramIterator& scan, BamReader* manager);
void fillin(DatagramIterator &scan, BamReader *manager);
public:

View File

@ -106,22 +106,22 @@ consider_rescale(PNMImage &pnmimage, const string &name) {
////////////////////////////////////////////////////////////////////
// Function: consider_downgrade
// Description: Reduces the number of channels in the texture, if
// necessary, according to num_components.
// necessary, according to num_channels.
////////////////////////////////////////////////////////////////////
static void
consider_downgrade(PNMImage &pnmimage, int num_components,
consider_downgrade(PNMImage &pnmimage, int num_channels,
const string &name) {
if (num_components != 0 && num_components < pnmimage.get_num_channels()) {
if (num_channels != 0 && num_channels < pnmimage.get_num_channels()) {
// One special case: we can't reduce from 3 to 2 components, since
// that would require adding an alpha channel.
if (pnmimage.get_num_channels() == 3 && num_components == 2) {
if (pnmimage.get_num_channels() == 3 && num_channels == 2) {
return;
}
gobj_cat.info()
<< "Downgrading " << name << " from " << pnmimage.get_num_channels()
<< " components to " << num_components << ".\n";
pnmimage.set_num_channels(num_components);
<< " components to " << num_channels << ".\n";
pnmimage.set_num_channels(num_channels);
}
}
@ -179,12 +179,12 @@ Texture::
// Function: read
// Access: Published
// Description: Reads the texture from the indicated filename. If
// num_components is not 0, it specifies the number of
// num_channels is not 0, it specifies the number of
// components to downgrade the image to if it is greater
// than this number.
////////////////////////////////////////////////////////////////////
bool Texture::
read(const Filename &fullpath, int num_components) {
read(const Filename &fullpath, int primary_file_num_channels) {
PNMImage image;
if (!image.read(fullpath)) {
@ -206,7 +206,11 @@ read(const Filename &fullpath, int num_components) {
// Check to see if we need to scale it.
consider_rescale(image, get_name());
consider_downgrade(image, num_components, get_name());
consider_downgrade(image, primary_file_num_channels, get_name());
_primary_file_num_channels = image.get_num_channels();
_alpha_file_channel = 0;
return load(image);
}
@ -218,7 +222,7 @@ read(const Filename &fullpath, int num_components) {
////////////////////////////////////////////////////////////////////
bool Texture::
read(const Filename &fullpath, const Filename &alpha_fullpath,
int num_components) {
int primary_file_num_channels, int alpha_file_channel) {
PNMImage image;
if (!image.read(fullpath)) {
gobj_cat.error()
@ -263,16 +267,44 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
alpha_image = scaled;
}
consider_downgrade(image, primary_file_num_channels, get_name());
_primary_file_num_channels = image.get_num_channels();
// Make the original image a 4-component image by taking the
// grayscale value from the second image.
image.add_alpha();
for (int x = 0; x < image.get_x_size(); x++) {
for (int y = 0; y < image.get_y_size(); y++) {
image.set_alpha(x, y, alpha_image.get_gray(x, y));
if (alpha_file_channel == 4 ||
(alpha_file_channel == 2 && alpha_image.get_num_channels() == 2)) {
// Use the alpha channel.
for (int x = 0; x < image.get_x_size(); x++) {
for (int y = 0; y < image.get_y_size(); y++) {
image.set_alpha(x, y, alpha_image.get_alpha(x, y));
}
}
_alpha_file_channel = alpha_image.get_num_channels();
} else if (alpha_file_channel >= 1 && alpha_file_channel <= 3 &&
alpha_image.get_num_channels() >= 3) {
// Use the appropriate red, green, or blue channel.
for (int x = 0; x < image.get_x_size(); x++) {
for (int y = 0; y < image.get_y_size(); y++) {
image.set_alpha(x, y, alpha_image.get_channel_val(x, y, alpha_file_channel - 1));
}
}
_alpha_file_channel = alpha_file_channel;
} else {
// Use the grayscale channel.
for (int x = 0; x < image.get_x_size(); x++) {
for (int y = 0; y < image.get_y_size(); y++) {
image.set_alpha(x, y, alpha_image.get_gray(x, y));
}
}
_alpha_file_channel = 0;
}
consider_downgrade(image, num_components, get_name());
return load(image);
}
@ -697,18 +729,16 @@ make_Texture(const FactoryParams &params) {
parse_params(params, scan, manager);
string name;
Filename filename, alpha_filename;
// Get the properties written by ImageBuffer::write_datagram().
name = scan.get_string();
filename = scan.get_string();
alpha_filename = scan.get_string();
string name = scan.get_string();
Filename filename = scan.get_string();
Filename alpha_filename = scan.get_string();
int primary_file_num_channels = 0;
int alpha_file_channel = 0;
// Get the expected number of components.
int num_components = 0;
if (manager->get_file_minor_ver() >= 2) {
num_components = scan.get_uint8();
if (manager->get_file_minor_ver() >= 3) {
primary_file_num_channels = scan.get_uint8();
alpha_file_channel = scan.get_uint8();
}
PT(Texture) me;
@ -722,9 +752,10 @@ make_Texture(const FactoryParams &params) {
} else {
// This texture does have a filename, so try to load it from disk.
if (alpha_filename.empty()) {
me = TexturePool::load_texture(filename, num_components);
me = TexturePool::load_texture(filename, primary_file_num_channels);
} else {
me = TexturePool::load_texture(filename, alpha_filename, num_components);
me = TexturePool::load_texture(filename, alpha_filename,
primary_file_num_channels, alpha_file_channel);
}
}
@ -766,21 +797,17 @@ fillin(DatagramIterator &scan, BamReader *manager) {
_magfilter = (enum FilterType) scan.get_uint8();
_anisotropic_degree = scan.get_int16();
if (scan.get_remaining_size() > 0) {
bool has_pbuffer = scan.get_bool();
if (has_pbuffer) {
PixelBuffer::Format format = (PixelBuffer::Format)scan.get_uint8();
int num_components = -1;
if (scan.get_remaining_size() > 0) {
num_components = scan.get_uint8();
}
bool has_pbuffer = scan.get_bool();
if (has_pbuffer) {
PixelBuffer::Format format = (PixelBuffer::Format)scan.get_uint8();
int num_channels = -1;
num_channels = scan.get_uint8();
if (_pbuffer != (PixelBuffer *)NULL) {
if (num_components == _pbuffer->get_num_components()) {
// Only reset the format if the number of components hasn't
// changed.
_pbuffer->set_format(format);
}
if (_pbuffer != (PixelBuffer *)NULL) {
if (num_channels == _pbuffer->get_num_components()) {
// Only reset the format if the number of components hasn't
// changed.
_pbuffer->set_format(format);
}
}
}
@ -800,11 +827,6 @@ write_datagram(BamWriter *manager, Datagram &me) {
// These properties are read in again by make_Texture(), above.
ImageBuffer::write_datagram(manager, me);
if (has_pbuffer) {
me.add_uint8(_pbuffer->get_num_components());
} else {
me.add_uint8(0);
}
// These properties are read in again by fillin(), above.
me.add_uint8(_wrapu);
@ -816,7 +838,6 @@ write_datagram(BamWriter *manager, Datagram &me) {
me.add_bool(has_pbuffer);
if (has_pbuffer) {
me.add_uint8(_pbuffer->get_format());
// I know this has already been written, above.
me.add_uint8(_pbuffer->get_num_components());
}
}

View File

@ -79,9 +79,9 @@ PUBLISHED:
bool bAllocateRAM);
~Texture();
bool read(const Filename &fullpath, int num_components = 0);
bool read(const Filename &fullpath, int primary_file_num_channels = 0);
bool read(const Filename &fullpath, const Filename &alpha_fullpath,
int num_components = 0);
int primary_file_num_channels = 0, int alpha_file_channel = 0);
bool write(const Filename &fullpath = "") const;
void set_wrapu(WrapMode wrap);

View File

@ -52,8 +52,8 @@ verify_texture(const string &filename) {
// file cannot be found, returns NULL.
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
load_texture(const string &filename, int num_components) {
return get_ptr()->ns_load_texture(filename, num_components);
load_texture(const string &filename, int primary_file_num_channels) {
return get_ptr()->ns_load_texture(filename, primary_file_num_channels);
}
////////////////////////////////////////////////////////////////////
@ -67,8 +67,10 @@ load_texture(const string &filename, int num_components) {
////////////////////////////////////////////////////////////////////
INLINE Texture *TexturePool::
load_texture(const string &filename, const string &alpha_filename,
int num_components) {
return get_ptr()->ns_load_texture(filename, alpha_filename, num_components);
int primary_file_num_channels, int alpha_file_channel) {
return get_ptr()->ns_load_texture(filename, alpha_filename,
primary_file_num_channels,
alpha_file_channel);
}
////////////////////////////////////////////////////////////////////

View File

@ -65,7 +65,7 @@ ns_has_texture(const Filename &orig_filename) {
// Description: The nonstatic implementation of load_texture().
////////////////////////////////////////////////////////////////////
Texture *TexturePool::
ns_load_texture(const Filename &orig_filename, int num_components) {
ns_load_texture(const Filename &orig_filename, int primary_file_num_channels) {
Filename filename(orig_filename);
if (!fake_texture_image.empty()) {
@ -92,7 +92,7 @@ ns_load_texture(const Filename &orig_filename, int num_components) {
gobj_cat.info()
<< "Loading texture " << filename << "\n";
PT(Texture) tex = new Texture;
if (!tex->read(filename, num_components)) {
if (!tex->read(filename, primary_file_num_channels)) {
// This texture was not found.
gobj_cat.error()
<< "Unable to read texture " << filename << "\n";
@ -114,12 +114,13 @@ ns_load_texture(const Filename &orig_filename, int num_components) {
Texture *TexturePool::
ns_load_texture(const Filename &orig_filename,
const Filename &orig_alpha_filename,
int num_components) {
int primary_file_num_channels,
int alpha_file_channel) {
Filename filename(orig_filename);
Filename alpha_filename(orig_alpha_filename);
if (!fake_texture_image.empty()) {
return ns_load_texture(fake_texture_image, num_components);
return ns_load_texture(fake_texture_image, primary_file_num_channels);
}
if (use_vfs) {
@ -149,7 +150,8 @@ ns_load_texture(const Filename &orig_filename,
<< "Loading texture " << filename << " and alpha component "
<< alpha_filename << endl;
PT(Texture) tex = new Texture;
if (!tex->read(filename, alpha_filename, num_components)) {
if (!tex->read(filename, alpha_filename, primary_file_num_channels,
alpha_file_channel)) {
// This texture was not found.
gobj_cat.error() << "Unable to read texture " << filename << "\n";
return NULL;

View File

@ -41,10 +41,11 @@ PUBLISHED:
INLINE static bool has_texture(const string &filename);
INLINE static bool verify_texture(const string &filename);
INLINE static Texture *load_texture(const string &filename,
int num_components = 0);
int primary_file_num_channels = 0);
INLINE static Texture *load_texture(const string &filename,
const string &alpha_filename,
int num_components = 0);
int primary_file_num_channels = 0,
int alpha_file_channel = 0);
INLINE static void add_texture(Texture *texture);
INLINE static void release_texture(Texture *texture);
INLINE static void release_all_textures();
@ -57,10 +58,11 @@ private:
INLINE TexturePool();
bool ns_has_texture(const Filename &orig_filename);
Texture *ns_load_texture(const Filename &orig_filename, int num_components);
Texture *ns_load_texture(const Filename &orig_filename, int primary_file_num_channels);
Texture *ns_load_texture(const Filename &orig_filename,
const Filename &orig_alpha_filename,
int num_components);
int primary_file_num_channels,
int alpha_file_channel);
void ns_add_texture(Texture *texture);
void ns_release_texture(Texture *texture);
void ns_release_all_textures();

View File

@ -26,20 +26,32 @@ INLINE ModelNode::
ModelNode(const string &name) :
PandaNode(name)
{
_preserve_transform = false;
_preserve_transform = PT_none;
}
////////////////////////////////////////////////////////////////////
// Function: ModelNode::set_preserve_transform
// Access: Public
// Description: Sets the preserve_transform flag. When this flag is
// true, flattening the scene graph will not flatten out
// any transformation assigned above this node;
// otherwise, any transforms applying to this node may
// or may not be flattened.
// Description: Sets the preserve_transform flag. This restricts the
// ability of a flatten operation to affect the
// transform stored on this node. If the flag is:
//
// PT_none - the transform may be adjusted at will.
//
// PT_local - the local (and net) transform should not
// be changed in any way. If necessary, an extra
// transform will be left on the node above to guarantee
// this. This is the strongest restriction.
//
// PT_net - preserve the net transform from the
// root, but it's acceptable to modify the local
// transform stored on this particular node if
// necessary, so long as the net transform is not
// changed. This eliminates the need to drop an extra
// transform on the node above.
////////////////////////////////////////////////////////////////////
INLINE void ModelNode::
set_preserve_transform(bool preserve_transform) {
set_preserve_transform(ModelNode::PreserveTransform preserve_transform) {
_preserve_transform = preserve_transform;
}
@ -49,7 +61,7 @@ set_preserve_transform(bool preserve_transform) {
// Description: Returns the current setting of the preserve_transform
// flag. See set_preserve_transform().
////////////////////////////////////////////////////////////////////
INLINE bool ModelNode::
INLINE ModelNode::PreserveTransform ModelNode::
get_preserve_transform() const {
return _preserve_transform;
}

View File

@ -62,7 +62,7 @@ safe_to_flatten() const {
////////////////////////////////////////////////////////////////////
bool ModelNode::
safe_to_transform() const {
return !_preserve_transform;
return _preserve_transform == PT_none;
}
////////////////////////////////////////////////////////////////////
@ -79,7 +79,7 @@ safe_to_transform() const {
////////////////////////////////////////////////////////////////////
bool ModelNode::
safe_to_modify_transform() const {
return !_preserve_transform;
return _preserve_transform != PT_local;
}
////////////////////////////////////////////////////////////////////
@ -129,7 +129,7 @@ register_with_read_factory() {
void ModelNode::
write_datagram(BamWriter *manager, Datagram &dg) {
PandaNode::write_datagram(manager, dg);
dg.add_bool(_preserve_transform);
dg.add_uint8((int)_preserve_transform);
}
////////////////////////////////////////////////////////////////////
@ -163,5 +163,5 @@ void ModelNode::
fillin(DatagramIterator &scan, BamReader *manager) {
PandaNode::fillin(scan, manager);
_preserve_transform = scan.get_bool();
_preserve_transform = (PreserveTransform)scan.get_uint8();
}

View File

@ -52,11 +52,17 @@ public:
virtual bool preserve_name() const;
PUBLISHED:
INLINE void set_preserve_transform(bool preserve_transform);
INLINE bool get_preserve_transform() const;
enum PreserveTransform {
PT_none,
PT_local,
PT_net
};
INLINE void set_preserve_transform(PreserveTransform preserve_transform);
INLINE PreserveTransform get_preserve_transform() const;
private:
bool _preserve_transform;
PreserveTransform _preserve_transform;
public:
static void register_with_read_factory();

View File

@ -34,9 +34,10 @@ static const unsigned short _bam_major_ver = 4;
// Bumped to major version 3 on 12/8/00 to change float64's to float32's.
// Bumped to major version 4 on 4/10/02 to store new scene graph.
static const unsigned short _bam_minor_ver = 2;
static const unsigned short _bam_minor_ver = 3;
// Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
// Bumped to minor version 2 on 4/12/03 to add num_components to texture.
// Bumped to minor version 3 on 4/15/03 to add ImageBuffer::_alpha_file_channel.
#endif