support cull face reverse

This commit is contained in:
David Rose 2003-04-10 22:02:41 +00:00
parent 5d86a43700
commit 6e686caf8c
18 changed files with 279 additions and 173 deletions

View File

@ -3979,7 +3979,7 @@ issue_depth_write(const DepthWriteAttrib *attrib) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian7::
issue_cull_face(const CullFaceAttrib *attrib) {
CullFaceAttrib::Mode mode = attrib->get_mode();
CullFaceAttrib::Mode mode = attrib->get_effective_mode();
switch (mode) {
case CullFaceAttrib::M_cull_none:

View File

@ -3717,7 +3717,7 @@ issue_depth_write(const DepthWriteAttrib *attrib) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
issue_cull_face(const CullFaceAttrib *attrib) {
CullFaceAttrib::Mode mode = attrib->get_mode();
CullFaceAttrib::Mode mode = attrib->get_effective_mode();
switch (mode) {
case CullFaceAttrib::M_cull_none:

View File

@ -611,6 +611,7 @@ do_enable_default_keys() {
_event_handler.add_hook("w", event_w, this);
_event_handler.add_hook("t", event_t, this);
_event_handler.add_hook("b", event_b, this);
_event_handler.add_hook("i", event_i, this);
_event_handler.add_hook("l", event_l, this);
_event_handler.add_hook("c", event_c, this);
_event_handler.add_hook("shift-c", event_C, this);
@ -712,6 +713,22 @@ event_b(CPT_Event event, void *) {
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaFramework::event_i
// Access: Protected, Static
// Description: Default handler for i key: invert one-sided faces.
////////////////////////////////////////////////////////////////////
void PandaFramework::
event_i(CPT_Event event, void *) {
if (event->get_num_parameters() == 1) {
EventParameter param = event->get_parameter(0);
WindowFramework *wf;
DCAST_INTO_V(wf, param.get_ptr());
wf->set_one_sided_reverse(!wf->get_one_sided_reverse());
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaFramework::event_l
// Access: Protected, Static

View File

@ -110,6 +110,7 @@ protected:
static void event_w(CPT_Event, void *data);
static void event_t(CPT_Event, void *data);
static void event_b(CPT_Event, void *data);
static void event_i(CPT_Event, void *data);
static void event_l(CPT_Event, void *data);
static void event_c(CPT_Event, void *data);
static void event_C(CPT_Event, void *data);

View File

@ -93,6 +93,16 @@ get_two_sided() const {
return _two_sided_enabled;
}
////////////////////////////////////////////////////////////////////
// Function: WindowFramework::get_one_sided_reverse
// Access: Public
// Description: Returns the current state of the one_sided_reverse flag.
////////////////////////////////////////////////////////////////////
INLINE bool WindowFramework::
get_one_sided_reverse() const {
return _one_sided_reverse_enabled;
}
////////////////////////////////////////////////////////////////////
// Function: WindowFramework::get_lighting
// Access: Public

View File

@ -39,6 +39,7 @@
#include "config_framework.h"
#include "depthTestAttrib.h"
#include "depthWriteAttrib.h"
#include "cullFaceAttrib.h"
#include "pgTop.h"
#include "geomNode.h"
#include "geomTristrip.h"
@ -70,6 +71,7 @@ WindowFramework(PandaFramework *panda_framework) :
_wireframe_enabled = false;
_texture_enabled = true;
_two_sided_enabled = false;
_one_sided_reverse_enabled = false;
_lighting_enabled = false;
_background_type = BT_default;
}
@ -136,6 +138,7 @@ close_window() {
_wireframe_enabled = false;
_texture_enabled = true;
_two_sided_enabled = false;
_one_sided_reverse_enabled = false;
_lighting_enabled = false;
}
@ -600,6 +603,10 @@ set_wireframe(bool enable) {
if (!_two_sided_enabled) {
render.clear_two_sided();
}
if (_one_sided_reverse_enabled) {
CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
render.node()->set_attrib(attrib);
}
}
_wireframe_enabled = enable;
@ -651,6 +658,35 @@ set_two_sided(bool enable) {
}
_two_sided_enabled = enable;
_one_sided_reverse_enabled = false;
}
////////////////////////////////////////////////////////////////////
// Function: WindowFramework::set_one_sided_reverse
// Access: Public
// Description: Toggles one-sided reverse mode. In this mode, the
// front sides of one-sided polygons are culled instead
// of the back side.
////////////////////////////////////////////////////////////////////
void WindowFramework::
set_one_sided_reverse(bool enable) {
if (enable == _one_sided_reverse_enabled) {
return;
}
NodePath render = get_render();
if (!_wireframe_enabled) {
if (enable) {
CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
render.node()->set_attrib(attrib);
} else {
render.clear_two_sided();
}
}
_two_sided_enabled = false;
_one_sided_reverse_enabled = enable;
}
////////////////////////////////////////////////////////////////////

View File

@ -88,12 +88,14 @@ public:
void set_wireframe(bool enable);
void set_texture(bool enable);
void set_two_sided(bool enable);
void set_one_sided_reverse(bool enable);
void set_lighting(bool enable);
void set_background_type(BackgroundType type);
INLINE bool get_wireframe() const;
INLINE bool get_texture() const;
INLINE bool get_two_sided() const;
INLINE bool get_one_sided_reverse() const;
INLINE bool get_lighting() const;
INLINE BackgroundType get_background_type() const;
@ -130,6 +132,7 @@ private:
bool _wireframe_enabled;
bool _texture_enabled;
bool _two_sided_enabled;
bool _one_sided_reverse_enabled;
bool _lighting_enabled;
BackgroundType _background_type;

View File

@ -2311,7 +2311,7 @@ issue_depth_write(const DepthWriteAttrib *attrib) {
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::
issue_cull_face(const CullFaceAttrib *attrib) {
CullFaceAttrib::Mode mode = attrib->get_mode();
CullFaceAttrib::Mode mode = attrib->get_effective_mode();
switch (mode) {
case CullFaceAttrib::M_cull_none:

View File

@ -24,17 +24,36 @@
// CullFaceAttrib object.
////////////////////////////////////////////////////////////////////
INLINE CullFaceAttrib::
CullFaceAttrib(CullFaceAttrib::Mode mode) :
_mode(mode)
CullFaceAttrib(CullFaceAttrib::Mode mode, bool reverse) :
_mode(mode),
_reverse(reverse)
{
}
////////////////////////////////////////////////////////////////////
// Function: CullFaceAttrib::get_mode
// Function: CullFaceAttrib::get_actual_mode
// Access: Published
// Description: Returns the culling mode.
// Description: Returns the actual culling mode, without considering
// the effects of the reverse flag. See also
// get_effective_mode().
////////////////////////////////////////////////////////////////////
INLINE CullFaceAttrib::Mode CullFaceAttrib::
get_mode() const {
get_actual_mode() const {
return _mode;
}
////////////////////////////////////////////////////////////////////
// Function: CullFaceAttrib::get_reverse
// Access: Published
// Description: Returns the 'reverse' flag. If this is true, the
// actual cull direction (clockwise
// vs. counterclockwise) is the reverse of what is
// specified here. This allows support for
// make_reverse(), which defines a CullFaceAttrib that
// reverses whatever the sense of culling would have
// been.
////////////////////////////////////////////////////////////////////
INLINE bool CullFaceAttrib::
get_reverse() const {
return _reverse;
}

View File

@ -34,13 +34,75 @@ TypeHandle CullFaceAttrib::_type_handle;
// are ordered counterclockwise when seen from the
// front, so the M_cull_clockwise will cull backfacing
// polygons.
//
// M_cull_unchanged is an identity attrib; if this is
// applied to vertices without any other intervening
// attrib, it is the same as applying the default
// attrib.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) CullFaceAttrib::
make(CullFaceAttrib::Mode mode) {
CullFaceAttrib *attrib = new CullFaceAttrib(mode);
CullFaceAttrib *attrib = new CullFaceAttrib(mode, false);
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: CullFaceAttrib::make_reverse
// Access: Published, Static
// Description: Constructs a new CullFaceAttrib object that reverses
// the effects of any other CullFaceAttrib objects in
// the scene graph. M_cull_clockwise will be treated as
// M_cull_counter_clockwise, and vice-versa.
// M_cull_none is unchanged.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) CullFaceAttrib::
make_reverse() {
CullFaceAttrib *attrib = new CullFaceAttrib(M_cull_unchanged, true);
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: CullFaceAttrib::get_effective_mode
// Access: Published
// Description: Returns the effective culling mode. This is the same
// as the actual culling mode, unless the reverse flag
// is set, which swaps CW for CCW and vice-versa. Also,
// M_cull_unchanged is mapped to M_cull_none.
////////////////////////////////////////////////////////////////////
CullFaceAttrib::Mode CullFaceAttrib::
get_effective_mode() const {
if (_reverse) {
switch (_mode) {
case M_cull_clockwise:
case M_cull_unchanged:
return M_cull_counter_clockwise;
case M_cull_counter_clockwise:
return M_cull_clockwise;
default:
break;
}
} else {
switch (_mode) {
case M_cull_clockwise:
case M_cull_unchanged:
return M_cull_clockwise;
case M_cull_counter_clockwise:
return M_cull_counter_clockwise;
default:
break;
}
}
return M_cull_none;
}
////////////////////////////////////////////////////////////////////
// Function: CullFaceAttrib::issue
// Access: Public, Virtual
@ -63,7 +125,7 @@ issue(GraphicsStateGuardianBase *gsg) const {
void CullFaceAttrib::
output(ostream &out) const {
out << get_type() << ":";
switch (get_mode()) {
switch (get_actual_mode()) {
case M_cull_none:
out << "cull_none";
break;
@ -73,6 +135,12 @@ output(ostream &out) const {
case M_cull_counter_clockwise:
out << "cull_counter_clockwise";
break;
case M_cull_unchanged:
out << "cull_unchanged";
break;
}
if (get_reverse()) {
out << "(reverse)";
}
}
@ -95,7 +163,81 @@ int CullFaceAttrib::
compare_to_impl(const RenderAttrib *other) const {
const CullFaceAttrib *ta;
DCAST_INTO_R(ta, other, 0);
return (int)_mode - (int)ta->_mode;
if (_mode != ta->_mode) {
return (int)_mode - (int)ta->_mode;
}
return (int)_reverse - (int)ta->_reverse;
}
////////////////////////////////////////////////////////////////////
// Function: CullFaceAttrib::compose_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderAttrib
// types to specify how two consecutive RenderAttrib
// objects of the same type interact.
//
// This should return the result of applying the other
// RenderAttrib to a node in the scene graph below this
// RenderAttrib, which was already applied. In most
// cases, the result is the same as the other
// RenderAttrib (that is, a subsequent RenderAttrib
// completely replaces the preceding one). On the other
// hand, some kinds of RenderAttrib (for instance,
// ColorTransformAttrib) might combine in meaningful
// ways.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) CullFaceAttrib::
compose_impl(const RenderAttrib *other) const {
const CullFaceAttrib *ta;
DCAST_INTO_R(ta, other, 0);
if (!_reverse && ta->_mode != M_cull_unchanged) {
// The normal case (there is nothing funny going on): the second
// attrib completely replaces this attrib.
return other;
}
// In the more complex case, the two attribs affect each other in
// some way, and we must generate a new attrib from the result.
Mode mode = _mode;
if (ta->_mode != M_cull_unchanged) {
mode = ta->_mode;
}
bool reverse = (_reverse && !ta->_reverse) || (!_reverse && ta->_reverse);
CullFaceAttrib *attrib = new CullFaceAttrib(mode, reverse);
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: CullFaceAttrib::invert_compose_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderAttrib
// types to specify how two consecutive RenderAttrib
// objects of the same type interact.
//
// See invert_compose() and compose_impl().
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) CullFaceAttrib::
invert_compose_impl(const RenderAttrib *other) const {
const CullFaceAttrib *ta;
DCAST_INTO_R(ta, other, 0);
// The invert case is the same as the normal case, except that the
// meaning of _reverse is inverted. See compose_impl(), above.
if (_reverse && ta->_mode != M_cull_unchanged) {
return other;
}
Mode mode = _mode;
if (ta->_mode != M_cull_unchanged) {
mode = ta->_mode;
}
bool reverse = (!_reverse && !ta->_reverse) || (_reverse && ta->_reverse);
CullFaceAttrib *attrib = new CullFaceAttrib(mode, reverse);
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
@ -111,7 +253,7 @@ compare_to_impl(const RenderAttrib *other) const {
////////////////////////////////////////////////////////////////////
RenderAttrib *CullFaceAttrib::
make_default_impl() const {
return new CullFaceAttrib;
return new CullFaceAttrib(M_cull_clockwise, false);
}
////////////////////////////////////////////////////////////////////
@ -136,6 +278,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_int8(_mode);
dg.add_bool(_reverse);
}
////////////////////////////////////////////////////////////////////
@ -148,7 +291,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
////////////////////////////////////////////////////////////////////
TypedWritable *CullFaceAttrib::
make_from_bam(const FactoryParams &params) {
CullFaceAttrib *attrib = new CullFaceAttrib;
CullFaceAttrib *attrib = new CullFaceAttrib(M_cull_none, false);
DatagramIterator scan;
BamReader *manager;
@ -170,4 +313,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_mode = (Mode)scan.get_int8();
if (manager->get_file_minor_ver() >= 1) {
_reverse = scan.get_bool();
}
}

View File

@ -34,15 +34,19 @@ PUBLISHED:
M_cull_none, // Cull no polygons
M_cull_clockwise, // Cull clockwise-oriented polygons
M_cull_counter_clockwise, // Cull counter-clockwise-oriented polygons
M_cull_unchanged, // Do not change existing cull behavior
};
private:
INLINE CullFaceAttrib(Mode mode = M_cull_clockwise);
INLINE CullFaceAttrib(Mode mode, bool reverse);
PUBLISHED:
static CPT(RenderAttrib) make(Mode mode = M_cull_clockwise);
static CPT(RenderAttrib) make_reverse();
INLINE Mode get_mode() const;
INLINE Mode get_actual_mode() const;
INLINE bool get_reverse() const;
Mode get_effective_mode() const;
public:
virtual void issue(GraphicsStateGuardianBase *gsg) const;
@ -50,10 +54,13 @@ public:
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
private:
Mode _mode;
bool _reverse;
public:
static void register_with_read_factory();

View File

@ -2057,7 +2057,7 @@ get_two_sided() const {
node()->get_attrib(CullFaceAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, attrib);
return (cfa->get_mode() == CullFaceAttrib::M_cull_none);
return (cfa->get_actual_mode() == CullFaceAttrib::M_cull_none);
}
return false;

View File

@ -34,7 +34,8 @@ 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 = 0;
static const unsigned short _bam_minor_ver = 1;
// Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
#endif

View File

@ -315,7 +315,7 @@ convert_geom_tri(GeomTri *geom, const RenderState *net_state,
const RenderAttrib *cf_attrib = net_state->get_attrib(CullFaceAttrib::get_class_type());
if (cf_attrib != (const RenderAttrib *)NULL) {
const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, cf_attrib);
if (cfa->get_mode() == CullFaceAttrib::M_cull_none) {
if (cfa->get_effective_mode() == CullFaceAttrib::M_cull_none) {
bface = true;
}
}
@ -617,155 +617,6 @@ get_egg_texture(Texture *tex) {
return NULL;
}
#if 0
////////////////////////////////////////////////////////////////////
// Function: BamToEgg::GeomState::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
BamToEgg::GeomState::
GeomState() {
_mat = LMatrix4f::ident_mat();
_tex_mat = LMatrix4f::ident_mat();
_color_mat = LMatrix4f::ident_mat();
_alpha_scale = 1.0;
_alpha_offset = 0.0;
_tex = (Texture *)NULL;
_bface = false;
}
////////////////////////////////////////////////////////////////////
// Function: BamToEgg::GeomState::get_net_state
// Access: Public
// Description: Gets the accumulated state of the indicated node (and
// its corresponding ArcChain) into the GeomState.
////////////////////////////////////////////////////////////////////
void BamToEgg::GeomState::
get_net_state(Node *node, ArcChain &chain, EggGroupNode *egg_parent) {
AllTransitionsWrapper atw;
wrt(node, chain.begin(), chain.end(),
(Node *)NULL,
atw, RenderRelation::get_class_type());
// Check for transform space.
const TransformTransition *tt;
if (get_transition_into(tt, atw)) {
_mat = tt->get_matrix();
LMatrix4f inv = LCAST(float, egg_parent->get_vertex_frame_inv());
_mat = _mat * inv;
}
// Check for texture matrix.
const TexMatrixTransition *tmt;
if (get_transition_into(tmt, atw)) {
_tex_mat = tmt->get_matrix();
}
// Check for color matrix.
const ColorMatrixTransition *cmt;
if (get_transition_into(cmt, atw)) {
_color_mat = cmt->get_matrix();
}
// Check for alpha scale/offset.
const AlphaTransformTransition *att;
if (get_transition_into(att, atw)) {
_alpha_scale = att->get_scale();
_alpha_offset = att->get_offset();
}
// Check for texture.
const TextureTransition *txt;
if (get_transition_into(txt, atw)) {
if (txt->is_on()) {
_tex = txt->get_texture();
}
}
// Check for bface.
const CullFaceTransition *cft;
if (get_transition_into(cft, atw)) {
if (cft->get_mode() == CullFaceProperty::M_cull_none) {
_bface = true;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: BamToEgg::GeomState::apply_vertex
// Access: Public
// Description: Applies the indicated vertex coordinate to the given
// EggVertex, after modifying it according to the
// current state.
////////////////////////////////////////////////////////////////////
void BamToEgg::GeomState::
apply_vertex(EggVertex &egg_vert, const Vertexf &vertex) {
LPoint3f transformed = vertex * _mat;
egg_vert.set_pos(LCAST(double, transformed));
}
////////////////////////////////////////////////////////////////////
// Function: BamToEgg::GeomState::apply_normal
// Access: Public
// Description: Applies the indicated vertex normal to the given
// EggVertex, after modifying it according to the
// current state.
////////////////////////////////////////////////////////////////////
void BamToEgg::GeomState::
apply_normal(EggVertex &egg_vert, const Normalf &normal) {
LPoint3f transformed = normal * _mat;
egg_vert.set_normal(LCAST(double, transformed));
}
////////////////////////////////////////////////////////////////////
// Function: BamToEgg::GeomState::apply_uv
// Access: Public
// Description: Applies the indicated vertex UV to the given
// EggVertex, after modifying it according to the
// current state.
////////////////////////////////////////////////////////////////////
void BamToEgg::GeomState::
apply_uv(EggVertex &egg_vert, const TexCoordf &uv) {
LVecBase4f v4(uv[0], uv[1], 0.0, 1.0);
v4 = v4 * _tex_mat;
egg_vert.set_uv(LCAST(double, uv));
}
////////////////////////////////////////////////////////////////////
// Function: BamToEgg::GeomState::apply_color
// Access: Public
// Description: Applies the indicated vertex color to the given
// EggVertex, after modifying it according to the
// current state.
////////////////////////////////////////////////////////////////////
void BamToEgg::GeomState::
apply_color(EggVertex &egg_vert, const Colorf &color) {
LPoint3f temp(color[0], color[1], color[2]);
temp = temp * _color_mat;
float alpha = (color[3] * _alpha_scale) +
_alpha_offset;
Colorf transformed(temp[0], temp[1], temp[2], alpha);
egg_vert.set_color(transformed);
}
////////////////////////////////////////////////////////////////////
// Function: BamToEgg::GeomState::apply_prim
// Access: Public
// Description: Applies generic, non-vertex-specific properties to
// the primitive.
////////////////////////////////////////////////////////////////////
void BamToEgg::GeomState::
apply_prim(EggPrimitive *egg_prim) {
if (_bface) {
egg_prim->set_bface_flag(true);
}
}
#endif
int main(int argc, char *argv[]) {
BamToEgg prog;

View File

@ -41,7 +41,7 @@ Palettizer *pal = (Palettizer *)NULL;
// allows us to easily update egg-palettize to write out additional
// information to its pi file, without having it increment the bam
// version number for all bam and boo files anywhere in the world.
int Palettizer::_pi_version = 7;
int Palettizer::_pi_version = 8;
// Updated to version 1 on 12/11/00 to add _remap_char_uv.
// Updated to version 2 on 12/19/00 to add TexturePlacement::_dest.
// Updated to version 3 on 12/19/00 to add PaletteGroup::_dependency_order.
@ -49,6 +49,7 @@ int Palettizer::_pi_version = 7;
// Updated to version 5 on 10/31/01 to add TextureProperties::_force_format.
// Updated to version 6 on 3/14/02 to add TextureImage::_alpha_mode.
// Updated to version 7 on 8/23/02 to add TextureProperties::_anisotropic_degree.
// Updated to version 8 on 3/20/03 to remove extensions from texture key names.
int Palettizer::_read_pi_version = 0;
@ -962,6 +963,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
for (i = 0; i < _num_textures; i++) {
TextureImage *texture;
DCAST_INTO_R(texture, p_list[index], index);
_textures.insert(Textures::value_type(texture->get_name(), texture));
index++;
}

View File

@ -1290,14 +1290,20 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
source->get_alpha_filename());
bool inserted = _sources.insert(Sources::value_type(key, source)).second;
nassertr(inserted, pi);
if (!inserted) {
nout << "Warning: texture key " << key
<< " is nonunique; texture lost.\n";
}
}
for (i = 0; i < _num_dests; i++) {
DestTextureImage *dest;
DCAST_INTO_R(dest, p_list[pi++], pi);
bool inserted = _dests.insert(Dests::value_type(dest->get_filename(), dest)).second;
nassertr(inserted, pi);
if (!inserted) {
nout << "Warning: dest filename " << dest->get_filename()
<< " is nonunique; texture lost.\n";
}
}
return pi;

View File

@ -106,7 +106,7 @@ from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex) {
_properties._magfilter = _egg_tex->get_magfilter();
_properties._anisotropic_degree = _egg_tex->get_anisotropic_degree();
string name = filename.get_basename();
string name = filename.get_basename_wo_extension();
TextureImage *texture = pal->get_texture(name);
_source_texture = texture->get_source(filename, alpha_filename);
_source_texture->update_properties(_properties);

View File

@ -73,7 +73,7 @@ parse(const string &line) {
vector_string::iterator wi;
for (wi = words.begin(); wi != words.end(); ++wi) {
const string &word = (*wi);
string word = (*wi);
// If the pattern ends in the string ".egg", and only if it ends
// in this string, it is deemed an egg pattern and will only be
@ -82,8 +82,15 @@ parse(const string &line) {
// textures.
if (word.length() > 4 && word.substr(word.length() - 4) == ".egg") {
_egg_patterns.push_back(GlobPattern(word));
} else {
_texture_patterns.push_back(GlobPattern(*wi));
// However, the filename extension, if any, is stripped off
// because the texture key names nowadays don't include them.
size_t dot = word.rfind('.');
if (dot != string::npos) {
word = word.substr(0, dot);
}
_texture_patterns.push_back(GlobPattern(word));
}
}