*** empty log message ***

This commit is contained in:
David Rose 2001-05-01 05:45:56 +00:00
parent 0a25316f29
commit 98a4f21207
25 changed files with 1231 additions and 64 deletions

View File

@ -19,7 +19,10 @@
eggFilenameNode.cxx eggFilenameNode.h eggGroup.I eggGroup.cxx \
eggGroup.h eggGroupNode.I eggGroupNode.cxx eggGroupNode.h \
eggGroupUniquifier.h eggGroupUniquifier.cxx \
eggMaterial.I eggMaterial.cxx eggMaterial.h eggMiscFuncs.I \
eggMaterial.I eggMaterial.cxx eggMaterial.h \
eggMaterialCollection.I eggMaterialCollection.cxx \
eggMaterialCollection.h \
eggMiscFuncs.I \
eggMiscFuncs.cxx eggMiscFuncs.h eggNamedObject.I eggNamedObject.cxx \
eggNamedObject.h eggNameUniquifier.cxx eggNameUniquifier.h \
eggNode.I eggNode.cxx eggNode.h eggNurbsCurve.I \
@ -51,7 +54,8 @@
eggExternalReference.h eggFilenameNode.I eggFilenameNode.h \
eggGroup.I eggGroup.h eggGroupNode.I eggGroupNode.h \
eggGroupUniquifier.h eggMaterial.I \
eggMaterial.h eggMorph.I eggMorph.h eggMorphList.I eggMorphList.h \
eggMaterial.h eggMaterialCollection.I eggMaterialCollection.h \
eggMorph.I eggMorph.h eggMorphList.I eggMorphList.h \
eggNamedObject.I eggNamedObject.h eggNameUniquifier.h eggNode.I eggNode.h \
eggNurbsCurve.I eggNurbsCurve.h eggNurbsSurface.I eggNurbsSurface.h \
eggObject.I eggObject.h eggParameters.h eggPoint.I eggPoint.h \

View File

@ -6,6 +6,7 @@
#include "eggData.h"
#include "eggCoordinateSystem.h"
#include "eggTextureCollection.h"
#include "eggMaterialCollection.h"
#include "eggComment.h"
#include "eggPoolUniquifier.h"
#include "config_egg.h"
@ -133,9 +134,9 @@ resolve_externals(const DSearchPath &searchpath) {
// Description: Removes duplicate references to the same texture
// image with the same properties. Considers two
// texture references with identical properties, but
// different tref names, to be the equivalent, and
// collapses them, choosing one tref name to keep
// arbitrarily. Returns the number of textures removed.
// different tref names, to be equivalent, and collapses
// them, choosing one tref name to keep arbitrarily.
// Returns the number of textures removed.
////////////////////////////////////////////////////////////////////
int EggData::
collapse_equivalent_textures() {
@ -145,6 +146,24 @@ collapse_equivalent_textures() {
textures.collapse_equivalent_textures(~EggTexture::E_tref_name, this);
}
////////////////////////////////////////////////////////////////////
// Function: EggData::collapse_equivalent_materials
// Access: Public
// Description: Removes duplicate references to the same material
// with the same properties. Considers two material
// references with identical properties, but different
// mref names, to be equivalent, and collapses them,
// choosing one mref name to keep arbitrarily. Returns
// the number of materials removed.
////////////////////////////////////////////////////////////////////
int EggData::
collapse_equivalent_materials() {
EggMaterialCollection materials;
materials.find_used_materials(this);
return
materials.collapse_equivalent_materials(~EggMaterial::E_mref_name, this);
}
////////////////////////////////////////////////////////////////////
// Function: EggData::write_egg
// Access: Public
@ -286,8 +305,17 @@ pre_write() {
textures.insert_textures(this, ci);
// Also make sure that the vertex pools and materials are uniquely
// named. This also checks textures, which is kind of redundant
// Do the same thing with the materials.
EggMaterialCollection materials;
materials.extract_materials(this);
materials.remove_unused_materials(this);
materials.collapse_equivalent_materials(~0, this);
materials.uniquify_mrefs();
materials.sort_by_mref();
materials.insert_materials(this, ci);
// Also make sure that the vertex pools are uniquely named. This
// also checks textures and materials, which is kind of redundant
// since we just did that, but we don't mind.
EggPoolUniquifier pu;
pu.uniquify(this);

View File

@ -44,6 +44,7 @@ public:
bool resolve_externals(const DSearchPath &searchpath = DSearchPath());
int collapse_equivalent_textures();
int collapse_equivalent_materials();
bool write_egg(Filename filename);
bool write_egg(ostream &out);

View File

@ -13,6 +13,7 @@
#include "eggVertexPool.h"
#include "eggVertex.h"
#include "eggTextureCollection.h"
#include "eggMaterialCollection.h"
#include "config_egg.h"
#include <dSearchPath.h>
@ -830,6 +831,52 @@ find_textures(EggTextureCollection *collection) {
return num_found;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::find_materials()
// Access: Protected
// Description: Walks the tree, looking for EggMaterials. Each
// EggMaterial that is found is removed from the
// hierarchy and added to the EggMaterialCollection.
// Returns the number of EggMaterials found.
////////////////////////////////////////////////////////////////////
int EggGroupNode::
find_materials(EggMaterialCollection *collection) {
int num_found = 0;
// We can do this ci/cnext iteration through the list as we modify
// it, only because we know this works with an STL list type
// container. If this were a vector or a set, this wouldn't
// necessarily work.
Children::iterator ci, cnext;
ci = _children.begin();
while (ci != _children.end()) {
cnext = ci;
++cnext;
EggNode *child = *ci;
if (child->is_of_type(EggMaterial::get_class_type())) {
PT(EggMaterial) tex = DCAST(EggMaterial, child);
// Now remove the EggMaterial entry from our child list.
prepare_remove_child(tex);
_children.erase(ci);
// And add it to the collection.
collection->add_material(tex);
num_found++;
} else if (child->is_of_type(EggGroupNode::get_class_type())) {
num_found +=
DCAST(EggGroupNode, child)->find_materials(collection);
}
ci = cnext;
}
return num_found;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::r_resolve_externals
// Access: Protected

View File

@ -18,6 +18,7 @@
#include <list>
class EggTextureCollection;
class EggMaterialCollection;
class EggPolygon;
class EggVertex;
class DSearchPath;
@ -119,6 +120,7 @@ protected:
CoordinateSystem find_coordsys_entry();
int find_textures(EggTextureCollection *collection);
int find_materials(EggMaterialCollection *collection);
bool r_resolve_externals(const DSearchPath &searchpath,
CoordinateSystem coordsys);
@ -163,6 +165,7 @@ private:
static TypeHandle _type_handle;
friend class EggTextureCollection;
friend class EggMaterialCollection;
};
#include "eggGroupNode.I"

View File

@ -141,7 +141,7 @@ get_emit() const {
if (has_emit()) {
return _emit;
} else {
return RGBColorf(1.0, 1.0, 1.0);
return RGBColorf(0.0, 0.0, 0.0);
}
}
@ -188,6 +188,116 @@ get_spec() const {
if (has_spec()) {
return _spec;
} else {
return RGBColorf(1.0, 1.0, 1.0);
return RGBColorf(0.0, 0.0, 0.0);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::set_shininess
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void EggMaterial::
set_shininess(double shininess) {
_shininess = shininess;
_flags |= F_shininess;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::clear_shininess
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void EggMaterial::
clear_shininess() {
_flags &= ~F_shininess;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::has_shininess
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool EggMaterial::
has_shininess() const {
return (_flags & F_shininess) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::get_shininess
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE double EggMaterial::
get_shininess() const {
if (has_shininess()) {
return _shininess;
} else {
return 0.0;
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::set_local
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void EggMaterial::
set_local(bool local) {
_local = local;
_flags |= F_local;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::clear_local
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void EggMaterial::
clear_local() {
_flags &= ~F_local;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::has_local
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool EggMaterial::
has_local() const {
return (_flags & F_local) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::get_local
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool EggMaterial::
get_local() const {
if (has_local()) {
return _local;
} else {
return 0.0;
}
}
////////////////////////////////////////////////////////////////////
// Function: UniqueEggMaterials::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE UniqueEggMaterials::
UniqueEggMaterials(int eq) : _eq(eq) {
}
////////////////////////////////////////////////////////////////////
// Function: UniqueEggMaterials::Function operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool UniqueEggMaterials::
operator ()(const EggMaterial *t1, const EggMaterial *t2) const {
return t1->sorts_less_than(*t2, _eq);
}

View File

@ -55,5 +55,127 @@ write(ostream &out, int indent_level) const {
<< "<Scalar> diffb { " << get_diff()[2] << " }\n";
}
if (has_amb()) {
indent(out, indent_level + 2)
<< "<Scalar> ambr { " << get_amb()[0] << " }\n";
indent(out, indent_level + 2)
<< "<Scalar> ambg { " << get_amb()[1] << " }\n";
indent(out, indent_level + 2)
<< "<Scalar> ambb { " << get_amb()[2] << " }\n";
}
if (has_emit()) {
indent(out, indent_level + 2)
<< "<Scalar> emitr { " << get_emit()[0] << " }\n";
indent(out, indent_level + 2)
<< "<Scalar> emitg { " << get_emit()[1] << " }\n";
indent(out, indent_level + 2)
<< "<Scalar> emitb { " << get_emit()[2] << " }\n";
}
if (has_spec()) {
indent(out, indent_level + 2)
<< "<Scalar> specr { " << get_spec()[0] << " }\n";
indent(out, indent_level + 2)
<< "<Scalar> specg { " << get_spec()[1] << " }\n";
indent(out, indent_level + 2)
<< "<Scalar> specb { " << get_spec()[2] << " }\n";
}
if (has_shininess()) {
indent(out, indent_level + 2)
<< "<Scalar> shininess { " << get_shininess() << " }\n";
}
if (has_local()) {
indent(out, indent_level + 2)
<< "<Scalar> local { " << get_local() << " }\n";
}
indent(out, indent_level) << "}\n";
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::is_equivalent_to
// Access: Public
// Description: Returns true if the two materials are equivalent in
// all relevant properties (according to eq), false
// otherwise.
//
// The Equivalence parameter, eq, should be set to the
// bitwise OR of the following properties, according to
// what you consider relevant:
//
// EggMaterial::E_attributes:
// All material attributes (diff, spec,
// etc.) except MRef name.
//
// EggMaterial::E_mref_name:
// The MRef name.
////////////////////////////////////////////////////////////////////
bool EggMaterial::
is_equivalent_to(const EggMaterial &other, int eq) const {
if (eq & E_attributes) {
if (_flags != other._flags ||
(has_diff() && get_diff() != other.get_diff()) ||
(has_amb() && get_amb() != other.get_amb()) ||
(has_emit() && get_emit() != other.get_emit()) ||
(has_spec() && get_spec() != other.get_spec()) ||
(has_shininess() && get_shininess() != other.get_shininess()) ||
(has_local() && get_local() != other.get_local())) {
return false;
}
}
if (eq & E_mref_name) {
if (get_name() != other.get_name()) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterial::sorts_less_than
// Access: Public
// Description: An ordering operator to compare two materials for
// sorting order. This imposes an arbitrary ordering
// useful to identify unique materials, according to the
// indicated Equivalence factor. See
// is_equivalent_to().
////////////////////////////////////////////////////////////////////
bool EggMaterial::
sorts_less_than(const EggMaterial &other, int eq) const {
if (eq & E_attributes) {
if (_flags != other._flags) {
return _flags < (int)other._flags;
}
if (has_diff() && get_diff() != other.get_diff()) {
return get_diff().compare_to(other.get_diff()) < 0;
}
if (has_amb() && get_amb() != other.get_amb()) {
return get_amb().compare_to(other.get_amb()) < 0;
}
if (has_emit() && get_emit() != other.get_emit()) {
return get_emit().compare_to(other.get_emit()) < 0;
}
if (has_spec() && get_spec() != other.get_spec()) {
return get_spec().compare_to(other.get_spec()) < 0;
}
if (has_shininess() && get_shininess() != other.get_shininess()) {
return get_shininess() < other.get_shininess() ? -1 : 1;
}
if (has_local() && get_local() != other.get_local()) {
return get_local() - other.get_local();
}
}
if (eq & E_mref_name) {
if (get_name() != other.get_name()) {
return get_name() < other.get_name();
}
}
return false;
}

View File

@ -23,6 +23,14 @@ public:
virtual void write(ostream &out, int indent_level) const;
enum Equivalence {
E_attributes = 0x001,
E_mref_name = 0x002,
};
bool is_equivalent_to(const EggMaterial &other, int eq) const;
bool sorts_less_than(const EggMaterial &other, int eq) const;
INLINE void set_diff(const RGBColorf &diff);
INLINE void clear_diff();
INLINE bool has_diff() const;
@ -43,18 +51,32 @@ public:
INLINE bool has_spec() const;
INLINE RGBColorf get_spec() const;
INLINE void set_shininess(double shininess);
INLINE void clear_shininess();
INLINE bool has_shininess() const;
INLINE double get_shininess() const;
INLINE void set_local(bool local);
INLINE void clear_local();
INLINE bool has_local() const;
INLINE bool get_local() const;
private:
enum Flags {
F_diff = 0x001,
F_amb = 0x002,
F_emit = 0x004,
F_spec = 0x008
F_diff = 0x001,
F_amb = 0x002,
F_emit = 0x004,
F_spec = 0x008,
F_shininess = 0x010,
F_local = 0x020
};
RGBColorf _diff;
RGBColorf _amb;
RGBColorf _emit;
RGBColorf _spec;
double _shininess;
bool _local;
int _flags;
@ -76,6 +98,21 @@ private:
static TypeHandle _type_handle;
};
///////////////////////////////////////////////////////////////////
// Class : UniqueEggMaterials
// Description : An STL function object for sorting materials into
// order by properties. Returns true if the two
// referenced EggMaterial pointers are in sorted order,
// false otherwise.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEGG UniqueEggMaterials {
public:
INLINE UniqueEggMaterials(int eq = ~0);
INLINE bool operator ()(const EggMaterial *t1, const EggMaterial *t2) const;
int _eq;
};
#include "eggMaterial.I"
#endif

View File

@ -0,0 +1,27 @@
// Filename: eggMaterialCollection.I
// Created by: drose (30Apr01)
//
////////////////////////////////////////////////////////////////////
INLINE EggMaterialCollection::iterator EggMaterialCollection::
begin() const {
nassertr(_ordered_materials.size() == _materials.size(),
_ordered_materials.begin());
return _ordered_materials.begin();
}
INLINE EggMaterialCollection::iterator EggMaterialCollection::
end() const {
return _ordered_materials.end();
}
INLINE bool EggMaterialCollection::
empty() const {
return _ordered_materials.empty();
}
INLINE EggMaterialCollection::size_type EggMaterialCollection::
size() const {
nassertr(_ordered_materials.size() == _materials.size(), 0);
return _ordered_materials.size();
}

View File

@ -0,0 +1,440 @@
// Filename: eggMaterialCollection.cxx
// Created by: drose (30Apr01)
//
////////////////////////////////////////////////////////////////////
#include "eggMaterialCollection.h"
#include "eggGroupNode.h"
#include "eggPrimitive.h"
#include "eggMaterial.h"
#include <nameUniquifier.h>
#include <algorithm>
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggMaterialCollection::
EggMaterialCollection() {
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggMaterialCollection::
EggMaterialCollection(const EggMaterialCollection &copy) :
_materials(copy._materials),
_ordered_materials(copy._ordered_materials)
{
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggMaterialCollection &EggMaterialCollection::
operator = (const EggMaterialCollection &copy) {
_materials = copy._materials;
_ordered_materials = copy._ordered_materials;
return *this;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::clear
// Access: Public
// Description: Removes all materials from the collection.
////////////////////////////////////////////////////////////////////
void EggMaterialCollection::
clear() {
_materials.clear();
_ordered_materials.clear();
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::extract_materials
// Access: Public
// Description: Walks the egg hierarchy beginning at the indicated
// node, and removes any EggMaterials encountered in the
// hierarchy, adding them to the collection. Returns
// the number of EggMaterials encountered.
////////////////////////////////////////////////////////////////////
int EggMaterialCollection::
extract_materials(EggGroupNode *node) {
// Since this traversal is destructive, we'll handle it within the
// EggGroupNode code.
return node->find_materials(this);
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::insert_materials
// Access: Public
// Description: Adds a series of EggMaterial nodes to the beginning of
// the indicated node to reflect each of the materials in
// the collection. Returns the number of material nodes
// added.
////////////////////////////////////////////////////////////////////
int EggMaterialCollection::
insert_materials(EggGroupNode *node) {
return insert_materials(node, node->begin());
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::insert_materials
// Access: Public
// Description: Adds a series of EggMaterial nodes to the beginning of
// the indicated node to reflect each of the materials in
// the collection. Returns the number of material nodes
// added.
////////////////////////////////////////////////////////////////////
int EggMaterialCollection::
insert_materials(EggGroupNode *node, EggGroupNode::iterator position) {
OrderedMaterials::iterator oti;
for (oti = _ordered_materials.begin();
oti != _ordered_materials.end();
++oti) {
node->insert(position, (*oti).p());
}
return size();
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::find_used_materials
// Access: Public
// Description: Walks the egg hierarchy beginning at the indicated
// node, looking for materials that are referenced by
// primitives but are not already members of the
// collection, adding them to the collection.
//
// If this is called following extract_materials(), it
// can be used to pick up any additional material
// references that appeared in the egg hierarchy (but
// whose EggMaterial node was not actually part of the
// hierarchy).
//
// If this is called in lieu of extract_materials(), it
// will fill up the collection with all of the
// referenced materials (and only the referenced
// materials), without destructively removing the
// EggMaterials from the hierarchy.
//
// This also has the side effect of incrementing the
// internal usage count for a material in the collection
// each time a material reference is encountered. This
// side effect is taken advantage of by
// remove_unused_materials().
////////////////////////////////////////////////////////////////////
int EggMaterialCollection::
find_used_materials(EggNode *node) {
int num_found = 0;
if (node->is_of_type(EggPrimitive::get_class_type())) {
EggPrimitive *primitive = DCAST(EggPrimitive, node);
if (primitive->has_material()) {
EggMaterial *tex = primitive->get_material();
Materials::iterator ti = _materials.find(tex);
if (ti == _materials.end()) {
// Here's a new material!
num_found++;
_materials.insert(Materials::value_type(tex, 1));
_ordered_materials.push_back(tex);
} else {
// Here's a material we'd already known about. Increment its
// usage count.
(*ti).second++;
}
}
} else if (node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *group = DCAST(EggGroupNode, node);
EggGroupNode::iterator ci;
for (ci = group->begin(); ci != group->end(); ++ci) {
EggNode *child = *ci;
num_found += find_used_materials(child);
}
}
return num_found;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::remove_unused_materials
// Access: Public
// Description: Removes any materials from the collection that aren't
// referenced by any primitives in the indicated egg
// hierarchy. This also, incidentally, adds materials to
// the collection that had been referenced by primitives
// but had not previously appeared in the collection.
////////////////////////////////////////////////////////////////////
void EggMaterialCollection::
remove_unused_materials(EggNode *node) {
// We'll do this the easy way: First, we'll remove *all* the
// materials from the collection, and then we'll add back only those
// that appear in the hierarchy.
clear();
find_used_materials(node);
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::collapse_equivalent_materials
// Access: Public
// Description: Walks through the collection and collapses together
// any separate materials that are equivalent according
// to the indicated equivalence factor, eq (see
// EggMaterial::is_equivalent_to()). The return value is
// the number of materials removed.
//
// This flavor of collapse_equivalent_materials()
// automatically adjusts all the primitives in the egg
// hierarchy to refer to the new material pointers.
////////////////////////////////////////////////////////////////////
int EggMaterialCollection::
collapse_equivalent_materials(int eq, EggGroupNode *node) {
MaterialReplacement removed;
int num_collapsed = collapse_equivalent_materials(eq, removed);
// And now walk the egg hierarchy and replace any references to a
// removed material with its replacement.
replace_materials(node, removed);
return num_collapsed;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::collapse_equivalent_materials
// Access: Public
// Description: Walks through the collection and collapses together
// any separate materials that are equivalent according
// to the indicated equivalence factor, eq (see
// EggMaterial::is_equivalent_to()). The return value is
// the number of materials removed.
//
// This flavor of collapse_equivalent_materials() does
// not adjust any primitives in the egg hierarchy;
// instead, it fills up the 'removed' map with an entry
// for each removed material, mapping it back to the
// equivalent retained material. It's up to the user to
// then call replace_materials() with this map, if
// desired, to apply these changes to the egg hierarchy.
////////////////////////////////////////////////////////////////////
int EggMaterialCollection::
collapse_equivalent_materials(int eq, EggMaterialCollection::MaterialReplacement &removed) {
int num_collapsed = 0;
typedef set<PT(EggMaterial), UniqueEggMaterials> Collapser;
UniqueEggMaterials uet(eq);
Collapser collapser(uet);
// First, put all of the materials into the Collapser structure, to
// find out the unique materials.
OrderedMaterials::const_iterator oti;
for (oti = _ordered_materials.begin();
oti != _ordered_materials.end();
++oti) {
EggMaterial *tex = (*oti);
pair<Collapser::const_iterator, bool> result = collapser.insert(tex);
if (!result.second) {
// This material is non-unique; another one was already there.
EggMaterial *first = *(result.first);
removed.insert(MaterialReplacement::value_type(tex, first));
num_collapsed++;
}
}
// Now record all of the unique materials only.
clear();
Collapser::const_iterator ci;
for (ci = collapser.begin(); ci != collapser.end(); ++ci) {
add_material(*ci);
}
return num_collapsed;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::replace_materials
// Access: Public, Static
// Description: Walks the egg hierarchy, changing out any reference
// to a material appearing on the left side of the map
// with its corresponding material on the right side.
// This is most often done following a call to
// collapse_equivalent_materials(). It does not directly
// affect the Collection.
////////////////////////////////////////////////////////////////////
void EggMaterialCollection::
replace_materials(EggGroupNode *node,
const EggMaterialCollection::MaterialReplacement &replace) {
EggGroupNode::iterator ci;
for (ci = node->begin();
ci != node->end();
++ci) {
EggNode *child = *ci;
if (child->is_of_type(EggPrimitive::get_class_type())) {
EggPrimitive *primitive = DCAST(EggPrimitive, child);
if (primitive->has_material()) {
PT(EggMaterial) tex = primitive->get_material();
MaterialReplacement::const_iterator ri;
ri = replace.find(tex);
if (ri != replace.end()) {
// Here's a material we want to replace.
primitive->set_material((*ri).second);
}
}
} else if (child->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *group_child = DCAST(EggGroupNode, child);
replace_materials(group_child, replace);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::uniquify_mrefs
// Access: Public
// Description: Guarantees that each material in the collection has a
// unique MRef name. This is essential before writing
// an egg file.
////////////////////////////////////////////////////////////////////
void EggMaterialCollection::
uniquify_mrefs() {
NameUniquifier nu(".mref", "mref");
OrderedMaterials::const_iterator oti;
for (oti = _ordered_materials.begin();
oti != _ordered_materials.end();
++oti) {
EggMaterial *tex = (*oti);
tex->set_name(nu.add_name(tex->get_name()));
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::sort_by_mref
// Access: Public
// Description: Sorts all the materials into alphabetical order by
// MRef name. Subsequent operations using begin()/end()
// will traverse in this sorted order.
////////////////////////////////////////////////////////////////////
void EggMaterialCollection::
sort_by_mref() {
sort(_ordered_materials.begin(), _ordered_materials.end(),
NamableOrderByName());
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::add_material
// Access: Public
// Description: Explicitly adds a new material to the collection.
// Returns true if the material was added, false if it
// was already there or if there was some error.
////////////////////////////////////////////////////////////////////
bool EggMaterialCollection::
add_material(EggMaterial *material) {
nassertr(_materials.size() == _ordered_materials.size(), false);
PT(EggMaterial) new_tex = material;
Materials::const_iterator ti;
ti = _materials.find(new_tex);
if (ti != _materials.end()) {
// This material is already a member of the collection.
return false;
}
_materials.insert(Materials::value_type(new_tex, 0));
_ordered_materials.push_back(new_tex);
nassertr(_materials.size() == _ordered_materials.size(), false);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::remove_material
// Access: Public
// Description: Explicitly removes a material from the collection.
// Returns true if the material was removed, false if it
// wasn't there or if there was some error.
////////////////////////////////////////////////////////////////////
bool EggMaterialCollection::
remove_material(EggMaterial *material) {
nassertr(_materials.size() == _ordered_materials.size(), false);
Materials::iterator ti;
ti = _materials.find(material);
if (ti == _materials.end()) {
// This material is not a member of the collection.
return false;
}
_materials.erase(ti);
OrderedMaterials::iterator oti;
PT(EggMaterial) ptex = material;
oti = find(_ordered_materials.begin(), _ordered_materials.end(), ptex);
nassertr(oti != _ordered_materials.end(), false);
_ordered_materials.erase(oti);
nassertr(_materials.size() == _ordered_materials.size(), false);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::create_unique_material
// Access: Public
// Description: Creates a new material if there is not already one
// equivalent (according to eq, see
// EggMaterial::is_equivalent_to()) to the indicated
// material, or returns the existing one if there is.
////////////////////////////////////////////////////////////////////
EggMaterial *EggMaterialCollection::
create_unique_material(const EggMaterial &copy, int eq) {
// This requires a complete linear traversal, not terribly
// efficient.
OrderedMaterials::const_iterator oti;
for (oti = _ordered_materials.begin();
oti != _ordered_materials.end();
++oti) {
EggMaterial *tex = (*oti);
if (copy.is_equivalent_to(*tex, eq)) {
return tex;
}
}
EggMaterial *new_material = new EggMaterial(copy);
add_material(new_material);
return new_material;
}
////////////////////////////////////////////////////////////////////
// Function: EggMaterialCollection::find_mref
// Access: Public
// Description: Returns the material with the indicated MRef name, or
// NULL if no material matches.
////////////////////////////////////////////////////////////////////
EggMaterial *EggMaterialCollection::
find_mref(const string &mref_name) const {
// This requires a complete linear traversal, not terribly
// efficient.
OrderedMaterials::const_iterator oti;
for (oti = _ordered_materials.begin();
oti != _ordered_materials.end();
++oti) {
EggMaterial *tex = (*oti);
if (tex->get_name() == mref_name) {
return tex;
}
}
return (EggMaterial *)NULL;
}

View File

@ -0,0 +1,92 @@
// Filename: eggMaterialCollection.h
// Created by: drose (30Apr01)
//
////////////////////////////////////////////////////////////////////
#ifndef EGGMATERIALCOLLECTION_H
#define EGGMATERIALCOLLECTION_H
#include <pandabase.h>
#include "eggMaterial.h"
#include "eggGroupNode.h"
#include <string>
#include <map>
////////////////////////////////////////////////////////////////////
// Class : EggMaterialCollection
// Description : This is a collection of materials by MRef name. It
// can extract the materials from an egg file and sort
// them all together; it can also manage the creation of
// unique materials and the assignment of unique MRef
// names.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEGG EggMaterialCollection {
// This is a bit of private interface stuff that must be here as a
// forward reference. This allows us to define the
// EggMaterialCollection as an STL container.
private:
typedef map<PT(EggMaterial), int> Materials;
typedef vector< PT(EggMaterial) > OrderedMaterials;
public:
typedef OrderedMaterials::const_iterator iterator;
typedef iterator const_iterator;
typedef OrderedMaterials::size_type size_type;
typedef map<PT(EggMaterial), PT(EggMaterial) > MaterialReplacement;
// Here begins the actual public interface to EggMaterialCollection.
public:
EggMaterialCollection();
EggMaterialCollection(const EggMaterialCollection &copy);
EggMaterialCollection &operator = (const EggMaterialCollection &copy);
void clear();
int extract_materials(EggGroupNode *node);
int insert_materials(EggGroupNode *node);
int insert_materials(EggGroupNode *node, EggGroupNode::iterator position);
int find_used_materials(EggNode *node);
void remove_unused_materials(EggNode *node);
int collapse_equivalent_materials(int eq, EggGroupNode *node);
int collapse_equivalent_materials(int eq, MaterialReplacement &removed);
static void replace_materials(EggGroupNode *node,
const MaterialReplacement &replace);
void uniquify_mrefs();
void sort_by_mref();
// Can be used to traverse all the materials in the collection, in
// order as last sorted.
INLINE iterator begin() const;
INLINE iterator end() const;
INLINE bool empty() const;
INLINE size_type size() const;
bool add_material(EggMaterial *material);
bool remove_material(EggMaterial *material);
// create_unique_material() creates a new material if there is not
// already one equivalent (according to eq, see
// EggMaterial::is_equivalent_to()) to the indicated material, or
// returns the existing one if there is.
EggMaterial *create_unique_material(const EggMaterial &copy, int eq);
// Find a material with a particular MRef name.
EggMaterial *find_mref(const string &mref_name) const;
private:
Materials _materials;
OrderedMaterials _ordered_materials;
};
#include "eggMaterialCollection.I"
#endif

View File

@ -196,17 +196,17 @@ is_equivalent_to(const EggTexture &other, int eq) const {
if (eq & E_basename) {
if (a.get_basename_wo_extension() != b.get_basename_wo_extension()) {
return false;
return false;
}
}
if (eq & E_extension) {
if (a.get_extension() != b.get_extension()) {
return false;
return false;
}
}
if (eq & E_dirname) {
if (a.get_dirname() != b.get_dirname()) {
return false;
return false;
}
}
}
@ -218,21 +218,21 @@ is_equivalent_to(const EggTexture &other, int eq) const {
if (has_transform() && other.has_transform()) {
if (!_transform.almost_equal(other._transform, 0.0001)) {
return false;
return false;
}
}
}
if (eq & E_attributes) {
if (_format != other._format ||
_wrap_mode != other._wrap_mode ||
_wrap_u != other._wrap_u ||
_wrap_v != other._wrap_v ||
_minfilter != other._minfilter ||
_magfilter != other._magfilter ||
_magfilteralpha != other._magfilteralpha ||
_magfiltercolor != other._magfiltercolor ||
_env_type != other._env_type) {
_wrap_mode != other._wrap_mode ||
_wrap_u != other._wrap_u ||
_wrap_v != other._wrap_v ||
_minfilter != other._minfilter ||
_magfilter != other._magfilter ||
_magfilteralpha != other._magfilteralpha ||
_magfiltercolor != other._magfiltercolor ||
_env_type != other._env_type) {
return false;
}
if (EggRenderMode::operator != (other)) {
@ -270,17 +270,17 @@ sorts_less_than(const EggTexture &other, int eq) const {
if (eq & E_basename) {
if (a.get_basename_wo_extension() != b.get_basename_wo_extension()) {
return a.get_basename_wo_extension() < b.get_basename_wo_extension();
return a.get_basename_wo_extension() < b.get_basename_wo_extension();
}
}
if (eq & E_extension) {
if (a.get_extension() != b.get_extension()) {
return a.get_extension() < b.get_extension();
return a.get_extension() < b.get_extension();
}
}
if (eq & E_dirname) {
if (a.get_dirname() != b.get_dirname()) {
return a.get_dirname() < b.get_dirname();
return a.get_dirname() < b.get_dirname();
}
}
}

View File

@ -165,7 +165,7 @@ private:
};
///////////////////////////////////////////////////////////////////
// Class : UniqueEggTextures
// Class : UniqueEggTextures
// Description : An STL function object for sorting textures into
// order by properties. Returns true if the two
// referenced EggTexture pointers are in sorted order,
@ -179,16 +179,6 @@ public:
int _eq;
};
///////////////////////////////////////////////////////////////////
// Class : TRefEggTextures
// Description : An STL function object for sorting textures into
// order by TRef name.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEGG TRefEggTextures {
public:
INLINE bool operator ()(const EggTexture *t1, const EggTexture *t2) const;
};
INLINE ostream &operator << (ostream &out, const EggTexture &n) {
return out << n.get_filename();
}

View File

@ -516,6 +516,12 @@ material_body:
spec[2] = value;
material->set_spec(spec);
} else if (cmp_nocase_uh(name, "shininess") == 0) {
material->set_shininess(value);
} else if (cmp_nocase_uh(name, "local") == 0) {
material->set_local(value != 0.0);
} else {
eggyywarning("Unsupported material scalar: " + name);
}

View File

@ -37,6 +37,9 @@
#include <builderVertex.h>
#include <texturePool.h>
#include <textureTransition.h>
#include <material.h>
#include <materialPool.h>
#include <materialTransition.h>
#include <transformTransition.h>
#include <transparencyTransition.h>
#include <cullFaceTransition.h>
@ -862,6 +865,65 @@ apply_texture_apply_attributes(TextureApplyTransition *apply,
}
}
////////////////////////////////////////////////////////////////////
// Function: EggLoader::get_material_transition
// Access: Private
// Description: Returns a transition suitable for enabling the
// material indicated by the given EggMaterial, and with
// the indicated backface flag.
////////////////////////////////////////////////////////////////////
MaterialTransition *EggLoader::
get_material_transition(const EggMaterial *egg_mat, bool bface) {
Materials &materials = bface ? _materials_bface : _materials;
// First, check whether we've seen this material before.
Materials::const_iterator mi;
mi = materials.find(egg_mat);
if (mi != materials.end()) {
return (*mi).second;
}
// Ok, this is the first time we've seen this particular
// EggMaterial. Create a new Material that matches it.
PT(Material) mat = new Material;
if (egg_mat->has_diff()) {
RGBColorf diff = egg_mat->get_diff();
mat->set_diffuse(Colorf(diff[0], diff[1], diff[2], 1.0));
// By default, ambient is the same as diffuse, if diffuse is
// specified but ambient is not.
mat->set_ambient(Colorf(diff[0], diff[1], diff[2], 1.0));
}
if (egg_mat->has_amb()) {
RGBColorf amb = egg_mat->get_amb();
mat->set_ambient(Colorf(amb[0], amb[1], amb[2], 1.0));
}
if (egg_mat->has_emit()) {
RGBColorf emit = egg_mat->get_emit();
mat->set_emission(Colorf(emit[0], emit[1], emit[2], 1.0));
}
if (egg_mat->has_spec()) {
RGBColorf spec = egg_mat->get_spec();
mat->set_specular(Colorf(spec[0], spec[1], spec[2], 1.0));
}
if (egg_mat->has_shininess()) {
mat->set_shininess(egg_mat->get_shininess());
}
if (egg_mat->has_local()) {
mat->set_local(egg_mat->get_local());
}
mat->set_twoside(bface);
// Now get a global Material pointer, shared with other models.
const Material *shared_mat = MaterialPool::get_material(mat);
// And create a MaterialTransition for this Material.
PT(MaterialTransition) mt = new MaterialTransition(shared_mat);
materials.insert(Materials::value_type(egg_mat, mt));
return mt;
}
////////////////////////////////////////////////////////////////////
// Function: EggLoader::setup_bucket
@ -957,6 +1019,13 @@ setup_bucket(BuilderBucket &bucket, NamedNode *parent,
}
}
if (egg_prim->has_material()) {
MaterialTransition *mt = get_material_transition(egg_prim->get_material(),
egg_prim->get_bface_flag());
bucket._trans.set_transition(mt);
}
// Also check the color of the primitive to see if we should assume
// alpha based on the alpha values specified in the egg file.
if (am == EggRenderMode::AM_unspecified) {

View File

@ -13,6 +13,7 @@
#include <eggData.h>
#include <eggTexture.h>
#include <eggGroup.h>
#include <eggMaterial.h>
#include <texture.h>
#include <namedNode.h>
#include <pt_NamedNode.h>
@ -22,6 +23,7 @@
#include <indirectCompareTo.h>
#include <textureTransition.h>
#include <textureApplyTransition.h>
#include <materialTransition.h>
class EggNode;
class EggBin;
@ -29,6 +31,7 @@ class EggTable;
class EggNurbsCurve;
class EggPrimitive;
class EggPolygon;
class EggMaterial;
class ComputedVerticesMaker;
class RenderRelation;
class CollisionSolid;
@ -73,6 +76,9 @@ private:
void apply_texture_apply_attributes(TextureApplyTransition *apply,
const EggTexture *egg_tex);
MaterialTransition *get_material_transition(const EggMaterial *egg_mat,
bool bface);
void setup_bucket(BuilderBucket &bucket, NamedNode *parent,
EggPrimitive *egg_prim);
@ -116,6 +122,10 @@ private:
typedef map<PT(EggTexture), TextureDef> Textures;
Textures _textures;
typedef map<CPT(EggMaterial), PT(MaterialTransition) > Materials;
Materials _materials;
Materials _materials_bface;
typedef set<RenderRelation *> Decals;
Decals _decals;

View File

@ -1159,3 +1159,20 @@ INLINE const float &GLGraphicsStateGuardian::
get_current_alpha_scale() const {
return _current_alpha_scale;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::report_errors
// Access: Protected
// Description: Checks for any outstanding error codes and outputs
// them, if found. If NDEBUG is defined, this function
// does nothing.
////////////////////////////////////////////////////////////////////
INLINE void GLGraphicsStateGuardian::
report_errors() const {
#ifndef NDEBUG
GLenum error_code = glGetError();
if (error_code != GL_NO_ERROR) {
report_errors_loop(error_code);
}
#endif
}

View File

@ -466,6 +466,7 @@ render_frame(const AllAttributesWrapper &initial_state) {
#endif
_win->begin_frame();
report_errors();
_decal_level = 0;
if (_clear_buffer_type != 0) {
@ -539,6 +540,7 @@ render_frame(const AllAttributesWrapper &initial_state) {
// more aware of whether their parameters or positions have changed
// at all?
report_errors();
_win->end_frame();
#ifdef GSG_VERBOSE
@ -740,6 +742,7 @@ draw_point(const GeomPoint *geom) {
}
glEnd();
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -799,6 +802,7 @@ draw_line(const GeomLine* geom) {
}
glEnd();
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -876,6 +880,7 @@ draw_linestrip(const GeomLinestrip* geom) {
}
glEnd();
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1181,6 +1186,7 @@ draw_sprite(const GeomSprite *geom) {
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(_current_projection_mat.get_data());
#endif
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1252,6 +1258,7 @@ draw_polygon(const GeomPolygon *geom) {
}
glEnd();
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1318,6 +1325,7 @@ draw_tri(const GeomTri *geom) {
}
glEnd();
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1384,6 +1392,7 @@ draw_quad(const GeomQuad *geom) {
}
glEnd();
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1472,6 +1481,7 @@ draw_tristrip(const GeomTristrip *geom) {
}
glEnd();
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1560,6 +1570,7 @@ draw_trifan(const GeomTrifan *geom) {
}
glEnd();
}
report_errors();
}
@ -1639,6 +1650,7 @@ draw_sphere(const GeomSphere *geom) {
}
gluDeleteQuadric(sph);
report_errors();
}
@ -1669,7 +1681,8 @@ prepare_texture(Texture *tex) {
// which shouldn't be possible, since the texture itself should
// detect this.
nassertr(inserted, NULL);
report_errors();
return gtc;
}
@ -1689,6 +1702,7 @@ apply_texture(TextureContext *tc) {
specify_texture(tex);
apply_texture_immediate(tex);
*/
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1715,6 +1729,7 @@ release_texture(TextureContext *tc) {
tex->clear_gsg(this);
delete gtc;
report_errors();
}
static int logs[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
@ -1898,6 +1913,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
texture_to_pixel_buffer(tc, pb, dr);
pop_frame_buffer(old_fb);
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1925,6 +1941,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb,
pb->_image = PTA_uchar(w * h * pb->get_num_components());
copy_pixel_buffer(pb, dr);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -1994,6 +2011,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
pb->_image.p() );
nassertv(!pb->_image.empty());
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2131,6 +2149,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
glPopMatrix();
pop_display_region(old_dr);
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2188,6 +2207,7 @@ void GLGraphicsStateGuardian::apply_material(const Material *material) {
call_glLightModelLocal(material->get_local());
call_glLightModelTwoSide(material->get_twoside());
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2211,6 +2231,7 @@ apply_fog(Fog *fog) {
break;
}
call_glFogColor(fog->get_color());
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2270,6 +2291,7 @@ void GLGraphicsStateGuardian::apply_light( PointLight* light )
glgsg_cat.debug()
<< "glPopMatrix()" << endl;
#endif
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2327,6 +2349,7 @@ void GLGraphicsStateGuardian::apply_light( DirectionalLight* light )
glgsg_cat.debug()
<< "glPopMatrix()" << endl;
#endif
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2382,6 +2405,7 @@ void GLGraphicsStateGuardian::apply_light( Spotlight* light )
glgsg_cat.debug()
<< "glPopMatrix()" << endl;
#endif
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2438,6 +2462,7 @@ issue_transform(const TransformAttribute *attrib) {
enable_texturing(texturing_was_enabled);
}
#endif
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2489,6 +2514,7 @@ issue_tex_matrix(const TexMatrixAttribute *attrib) {
#endif
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(attrib->get_matrix().get_data());
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2503,6 +2529,7 @@ issue_color(const ColorAttribute *attrib) {
const Colorf c = attrib->get_color();
glColor4f(c[0], c[1], c[2], c[3]);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2522,6 +2549,7 @@ issue_texture(const TextureAttribute *attrib) {
} else {
enable_texturing(false);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2574,6 +2602,7 @@ issue_tex_gen(const TexGenAttribute *attrib) {
<< "Unknown texgen mode " << (int)mode << endl;
break;
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2589,6 +2618,7 @@ issue_material(const MaterialAttribute *attrib) {
nassertv(material != (const Material *)NULL);
apply_material(material);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2608,6 +2638,7 @@ issue_fog(const FogAttribute *attrib) {
} else {
enable_fog(false);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2636,6 +2667,7 @@ issue_render_mode(const RenderModeAttribute *attrib) {
glgsg_cat.error()
<< "Unknown render mode " << (int)mode << endl;
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2732,6 +2764,7 @@ void GLGraphicsStateGuardian::issue_light(const LightAttribute *attrib )
} else {
call_glLightModelAmbient(_cur_ambient_light);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2769,6 +2802,7 @@ issue_color_blend(const ColorBlendAttribute *attrib) {
<< "Unknown color blend mode " << (int)mode << endl;
break;
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2781,6 +2815,7 @@ issue_texture_apply(const TextureApplyAttribute *attrib) {
// activate();
GLint glmode = get_texture_apply_mode_type(attrib->get_mode());
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glmode);
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2792,9 +2827,10 @@ void GLGraphicsStateGuardian::
issue_color_mask(const ColorMaskAttribute *attrib) {
// activate();
glColorMask(attrib->is_write_r(),
attrib->is_write_g(),
attrib->is_write_b(),
attrib->is_write_a());
attrib->is_write_g(),
attrib->is_write_b(),
attrib->is_write_a());
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2813,6 +2849,7 @@ issue_depth_test(const DepthTestAttribute *attrib) {
enable_depth_test(true);
glDepthFunc(get_depth_func_type(mode));
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2825,6 +2862,7 @@ issue_depth_write(const DepthWriteAttribute *attrib) {
// activate();
call_glDepthMask(attrib->is_on());
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2845,6 +2883,7 @@ issue_stencil(const StencilAttribute *attrib) {
call_glStencilFunc(get_stencil_func_type(mode));
call_glStencilOp(get_stencil_action_type(attrib->get_action()));
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2879,6 +2918,7 @@ issue_cull_face(const CullFaceAttribute *attrib) {
<< "invalid cull face mode " << (int)mode << endl;
break;
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -2967,6 +3007,7 @@ issue_clip_plane(const ClipPlaneAttribute *attrib)
if (_cur_clip_plane_enabled[i] == false)
enable_clip_plane(i, false);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3027,6 +3068,7 @@ issue_transparency(const TransparencyAttribute *attrib )
<< "invalid transparency mode " << (int)mode << endl;
break;
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3038,6 +3080,7 @@ void GLGraphicsStateGuardian::
issue_linesmooth(const LinesmoothAttribute *attrib) {
// activate();
enable_line_smooth(attrib->is_on());
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3053,6 +3096,7 @@ issue_point_shape(const PointShapeAttribute *attrib) {
glDisable(GL_POINT_SMOOTH);
else
glEnable(GL_POINT_SMOOTH);
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3080,6 +3124,7 @@ issue_polygon_offset(const PolygonOffsetAttribute *attrib) {
{
enable_polygon_offset(false);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3180,6 +3225,7 @@ begin_decal(GeomNode *base_geom) {
// buffer write off during this.
}
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3279,6 +3325,7 @@ end_decal(GeomNode *base_geom) {
enable_texturing(was_textured);
}
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3299,6 +3346,24 @@ compute_distance_to(const LPoint3f &point) const {
return -point[2];
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::report_errors_loop
// Access: Protected
// Description: The internal implementation of report_errors().
// Don't call this function; use report_errors()
// instead.
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::
report_errors_loop(GLenum error_code) const {
#ifndef NDEBUG
while (error_code != GL_NO_ERROR) {
glgsg_cat.error()
<< gluErrorString(error_code) << "\n";
error_code = glGetError();
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::set_draw_buffer
// Access: Protected
@ -3345,6 +3410,7 @@ set_draw_buffer(const RenderBuffer &rb) {
default:
call_glDrawBuffer(GL_FRONT_AND_BACK);
}
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3393,6 +3459,7 @@ set_read_buffer(const RenderBuffer &rb) {
default:
call_glReadBuffer(GL_FRONT_AND_BACK);
}
report_errors();
}
@ -3413,6 +3480,7 @@ bind_texture(TextureContext *tc) {
<< ")" << endl;
#endif
glBindTexture(GL_TEXTURE_2D, gtc->_index);
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3438,6 +3506,7 @@ specify_texture(Texture *tex) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
get_texture_filter_type(tex->get_magfilter()));
}
report_errors();
}
@ -3494,6 +3563,7 @@ apply_texture_immediate(Texture *tex) {
glTexImage2D( GL_TEXTURE_2D, 0, internal_format,
pb->get_xsize(), pb->get_ysize(), pb->get_border(),
external_format, type, pb->_image );
report_errors();
}
////////////////////////////////////////////////////////////////////
@ -3688,17 +3758,16 @@ get_internal_image_format(PixelBuffer::Format format) {
GLint GLGraphicsStateGuardian::
get_texture_apply_mode_type( TextureApplyProperty::Mode am ) const
{
switch( am )
{
case TextureApplyProperty::M_modulate: return GL_MODULATE;
case TextureApplyProperty::M_decal: return GL_DECAL;
case TextureApplyProperty::M_blend: return GL_BLEND;
case TextureApplyProperty::M_replace: return GL_REPLACE;
case TextureApplyProperty::M_add: return GL_ADD;
}
glgsg_cat.error()
<< "Invalid TextureApplyProperty::Mode value" << endl;
return GL_MODULATE;
switch( am ) {
case TextureApplyProperty::M_modulate: return GL_MODULATE;
case TextureApplyProperty::M_decal: return GL_DECAL;
case TextureApplyProperty::M_blend: return GL_BLEND;
case TextureApplyProperty::M_replace: return GL_REPLACE;
case TextureApplyProperty::M_add: return GL_ADD;
}
glgsg_cat.error()
<< "Invalid TextureApplyProperty::Mode value" << endl;
return GL_MODULATE;
}
////////////////////////////////////////////////////////////////////

View File

@ -222,6 +222,9 @@ protected:
INLINE GLenum get_light_id(int index) const;
INLINE GLenum get_clip_plane_id(int index) const;
INLINE void report_errors() const;
void report_errors_loop(GLenum error_code) const;
void set_draw_buffer(const RenderBuffer &rb);
void set_read_buffer(const RenderBuffer &rb);

View File

@ -285,7 +285,11 @@ get_local() const {
////////////////////////////////////////////////////////////////////
INLINE void Material::
set_local(bool local) {
_flags |= F_local;
if (local) {
_flags |= F_local;
} else {
_flags &= ~F_local;
}
}
////////////////////////////////////////////////////////////////////
@ -305,7 +309,11 @@ get_twoside() const {
////////////////////////////////////////////////////////////////////
INLINE void Material::
set_twoside(bool twoside) {
_flags = F_twoside;
if (twoside) {
_flags |= F_twoside;
} else {
_flags &= ~F_twoside;
}
}
////////////////////////////////////////////////////////////////////

View File

@ -74,10 +74,22 @@ compare_to(const Material &other) const {
////////////////////////////////////////////////////////////////////
void Material::
output(ostream &out) const {
out << "a" << get_ambient()[0] << ",d" << get_diffuse()[0]
<< ",s" << get_specular()[0] << ",e" << get_emission()[0]
<< ",s" << get_shininess() << ",l" << get_local()
<< ",t" << get_twoside();
out << "material";
if (has_ambient()) {
out << " a(" << get_ambient() << ")";
}
if (has_diffuse()) {
out << " d(" << get_diffuse() << ")";
}
if (has_specular()) {
out << " s(" << get_specular() << ")";
}
if (has_emission()) {
out << " e(" << get_emission() << ")";
}
out << " s" << get_shininess()
<< " l" << get_local()
<< " t" << get_twoside();
}
////////////////////////////////////////////////////////////////////
@ -87,10 +99,23 @@ output(ostream &out) const {
////////////////////////////////////////////////////////////////////
void Material::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << "ambient = " << get_ambient() << "\n";
indent(out, indent_level) << "diffuse = " << get_diffuse() << "\n";
indent(out, indent_level) << "specular = " << get_specular() << "\n";
indent(out, indent_level) << "emission = " << get_emission() << "\n";
bool any = false;
if (has_ambient()) {
indent(out, indent_level) << "ambient = " << get_ambient() << "\n";
any = true;
}
if (has_diffuse()) {
indent(out, indent_level) << "diffuse = " << get_diffuse() << "\n";
any = true;
}
if (has_specular()) {
indent(out, indent_level) << "specular = " << get_specular() << "\n";
any = true;
}
if (has_emission()) {
indent(out, indent_level) << "emission = " << get_emission() << "\n";
any = true;
}
indent(out, indent_level) << "shininess = " << get_shininess() << "\n";
indent(out, indent_level) << "local = " << get_local() << "\n";
indent(out, indent_level) << "twoside = " << get_twoside() << "\n";

View File

@ -29,6 +29,8 @@ CLwoSurface(LwoToEggConverter *converter, const LwoSurface *surface) :
_surface(surface)
{
_flags = 0;
_color.set(1.0, 1.0, 1.0);
_checked_material = false;
_checked_texture = false;
_map_uvs = NULL;
_block = (CLwoSurfaceBlock *)NULL;
@ -146,6 +148,10 @@ apply_properties(EggPrimitive *egg_prim, vector_PT_EggVertex &egg_vertices,
}
}
if (check_material()) {
egg_prim->set_material(_egg_material);
}
// We treat color and transparency separately, because Lightwave
// does, and this will allow us to treat inherited surfaces a little
// more robustly.
@ -269,6 +275,50 @@ check_texture() {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: CLwoSurface::check_material
// Access: Public
// Description: Checks whether the surface demands a material or not.
// Returns true if so, false otherwise.
////////////////////////////////////////////////////////////////////
bool CLwoSurface::
check_material() {
if (_checked_material) {
return (_egg_material != (EggMaterial *)NULL);
}
_checked_material = true;
_egg_material = (EggMaterial *)NULL;
if (!_converter->_make_materials) {
// If we aren't making materials, then don't make a material.
return false;
}
_egg_material = new EggMaterial(get_name());
RGBColorf color = _color;
if (check_texture()) {
// Texturing overrides the color.
color.set(1.0, 1.0, 1.0);
}
if ((_flags & F_diffuse) != 0) {
RGBColorf diffuse = color * _diffuse;
_egg_material->set_diff(diffuse);
}
if ((_flags & F_luminosity) != 0) {
RGBColorf luminosity = color * _luminosity;
_egg_material->set_emit(luminosity);
}
if ((_flags & F_specular) != 0) {
RGBColorf specular = color * _specular;
_egg_material->set_spec(specular);
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: CLwoSurface::generate_uvs
// Access: Private

View File

@ -13,6 +13,7 @@
#include <lwoSurface.h>
#include <luse.h>
#include <eggTexture.h>
#include <eggMaterial.h>
#include <vector_PT_EggVertex.h>
#include <map>
@ -38,10 +39,12 @@ public:
vector_PT_EggVertex &egg_vertices,
float &smooth_angle);
bool check_texture();
bool check_material();
INLINE bool has_named_uvs() const;
INLINE const string &get_uv_name() const;
enum Flags {
F_color = 0x0001,
F_diffuse = 0x0002,
@ -68,6 +71,9 @@ public:
LwoToEggConverter *_converter;
CPT(LwoSurface) _surface;
bool _checked_material;
PT(EggMaterial) _egg_material;
bool _checked_texture;
PT(EggTexture) _egg_texture;

View File

@ -31,6 +31,7 @@
LwoToEggConverter::
LwoToEggConverter() {
_generic_layer = (CLwoLayer *)NULL;
_make_materials = true;
}
////////////////////////////////////////////////////////////////////

View File

@ -45,6 +45,8 @@ public:
CLwoSurface *get_surface(const string &name) const;
bool _make_materials;
private:
void cleanup();