Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
7f23c901a5

+ 23 - 28
panda/src/collide/collisionSphere.cxx

@@ -339,6 +339,16 @@ intersects_line(double &t1, double &t2,
   return true;
   return true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSphere::register_with_read_factory
+//       Access: Public, Static
+//  Description: Factory method to generate a CollisionSphere object
+////////////////////////////////////////////////////////////////////
+void CollisionSphere::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_CollisionSphere);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionSphere::write_datagram
 //     Function: CollisionSphere::write_datagram
 //       Access: Public
 //       Access: Public
@@ -346,37 +356,19 @@ intersects_line(double &t1, double &t2,
 //               the particular object to a Datagram
 //               the particular object to a Datagram
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CollisionSphere::
 void CollisionSphere::
-write_datagram(BamWriter *manager, Datagram &me)
-{
+write_datagram(BamWriter *manager, Datagram &me) {
   CollisionSolid::write_datagram(manager, me);
   CollisionSolid::write_datagram(manager, me);
   _center.write_datagram(me);
   _center.write_datagram(me);
   me.add_float32(_radius);
   me.add_float32(_radius);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionSphere::fillin
-//       Access: Protected
-//  Description: Function that reads out of the datagram (or asks
-//               manager to read) all of the data that is needed to
-//               re-create this object and stores it in the appropiate
-//               place
-////////////////////////////////////////////////////////////////////
-void CollisionSphere::
-fillin(DatagramIterator& scan, BamReader* manager)
-{
-  CollisionSolid::fillin(scan, manager);
-  _center.read_datagram(scan);
-  _radius = scan.get_float32();
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionSphere::make_CollisionSphere
 //     Function: CollisionSphere::make_CollisionSphere
 //       Access: Protected
 //       Access: Protected
 //  Description: Factory method to generate a CollisionSphere object
 //  Description: Factory method to generate a CollisionSphere object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-TypedWriteable* CollisionSphere::
-make_CollisionSphere(const FactoryParams &params)
-{
+TypedWriteable *CollisionSphere::
+make_CollisionSphere(const FactoryParams &params) {
   CollisionSphere *me = new CollisionSphere;
   CollisionSphere *me = new CollisionSphere;
   BamReader *manager;
   BamReader *manager;
   Datagram packet;
   Datagram packet;
@@ -389,13 +381,16 @@ make_CollisionSphere(const FactoryParams &params)
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionSphere::register_with_factory
-//       Access: Public, Static
-//  Description: Factory method to generate a CollisionSphere object
+//     Function: CollisionSphere::fillin
+//       Access: Protected
+//  Description: Function that reads out of the datagram (or asks
+//               manager to read) all of the data that is needed to
+//               re-create this object and stores it in the appropiate
+//               place
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CollisionSphere::
 void CollisionSphere::
-register_with_read_factory(void)
-{
-  BamReader::get_factory()->register_factory(get_class_type(), make_CollisionSphere);
+fillin(DatagramIterator& scan, BamReader* manager) {
+  CollisionSolid::fillin(scan, manager);
+  _center.read_datagram(scan);
+  _radius = scan.get_float32();
 }
 }
-

+ 4 - 5
panda/src/collide/collisionSphere.h

@@ -66,13 +66,12 @@ private:
   float _radius;
   float _radius;
 
 
 public:
 public:
-  static void register_with_read_factory(void);
-  virtual void write_datagram(BamWriter* manager, Datagram &me);  
-
-  static TypedWriteable *make_CollisionSphere(const FactoryParams &params);
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &me);  
 
 
 protected:
 protected:
-  void fillin(DatagramIterator& scan, BamReader* manager);
+  static TypedWriteable *make_CollisionSphere(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 4 - 4
panda/src/dxgsg/dxGraphicsStateGuardian.cxx

@@ -3648,7 +3648,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian::apply_material( Material* material ) {
+void DXGraphicsStateGuardian::apply_material( const Material* material ) {
 	D3DMATERIAL7 cur_material;
 	D3DMATERIAL7 cur_material;
 	cur_material.dcvDiffuse = *(D3DCOLORVALUE *)(material->get_diffuse().get_data());
 	cur_material.dcvDiffuse = *(D3DCOLORVALUE *)(material->get_diffuse().get_data());
 	cur_material.dcvAmbient = *(D3DCOLORVALUE *)(material->get_ambient().get_data());
 	cur_material.dcvAmbient = *(D3DCOLORVALUE *)(material->get_ambient().get_data());
@@ -4131,9 +4131,9 @@ void DXGraphicsStateGuardian::
 issue_material(const MaterialAttribute *attrib) {
 issue_material(const MaterialAttribute *attrib) {
 	activate();
 	activate();
 	if (attrib->is_on()) {
 	if (attrib->is_on()) {
-		Material *material = attrib->get_material();
-		nassertv(material != (Material *)NULL);
-		material->apply(this);
+		const Material *material = attrib->get_material();
+		nassertv(material != (const Material *)NULL);
+		apply_material(material);
 	}
 	}
 }
 }
 
 

+ 1 - 1
panda/src/dxgsg/dxGraphicsStateGuardian.h

@@ -132,7 +132,7 @@ public:
                                  const RenderBuffer &rb,
                                  const RenderBuffer &rb,
 				 const NodeAttributes& na=NodeAttributes());
 				 const NodeAttributes& na=NodeAttributes());
 
 
-  virtual void apply_material(Material* material);
+  virtual void apply_material(const Material *material);
   virtual void apply_fog(Fog *fog);
   virtual void apply_fog(Fog *fog);
 
 
   virtual void apply_light(PointLight* light);
   virtual void apply_light(PointLight* light);

+ 147 - 6
panda/src/egg/eggMaterial.I

@@ -10,9 +10,9 @@
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void EggMaterial::
 INLINE void EggMaterial::
-set_diff(const Colorf &diff) {
+set_diff(const RGBColorf &diff) {
   _diff = diff;
   _diff = diff;
-  _has_diff = true;
+  _flags |= F_diff;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -22,7 +22,7 @@ set_diff(const Colorf &diff) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void EggMaterial::
 INLINE void EggMaterial::
 clear_diff() {
 clear_diff() {
-  _has_diff = false;
+  _flags &= ~F_diff;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -32,7 +32,7 @@ clear_diff() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool EggMaterial::
 INLINE bool EggMaterial::
 has_diff() const {
 has_diff() const {
-  return _has_diff;
+  return (_flags & F_diff) != 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -42,11 +42,152 @@ has_diff() const {
 //               false.  If so, it simply returns the default diff
 //               false.  If so, it simply returns the default diff
 //               color.
 //               color.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE Colorf EggMaterial::
+INLINE RGBColorf EggMaterial::
 get_diff() const {
 get_diff() const {
   if (has_diff()) {
   if (has_diff()) {
     return _diff;
     return _diff;
   } else {
   } else {
-    return Colorf(1.0, 1.0, 1.0, 1.0);
+    return RGBColorf(1.0, 1.0, 1.0);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::set_amb
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void EggMaterial::
+set_amb(const RGBColorf &amb) {
+  _amb = amb;
+  _flags |= F_amb;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::clear_amb
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void EggMaterial::
+clear_amb() {
+  _flags &= ~F_amb;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::has_amb
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool EggMaterial::
+has_amb() const {
+  return (_flags & F_amb) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::get_amb
+//       Access: Public
+//  Description: It is legal to call this even if has_amb() returns
+//               false.  If so, it simply returns the default amb
+//               color.
+////////////////////////////////////////////////////////////////////
+INLINE RGBColorf EggMaterial::
+get_amb() const {
+  if (has_amb()) {
+    return _amb;
+  } else {
+    return RGBColorf(1.0, 1.0, 1.0);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::set_emit
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void EggMaterial::
+set_emit(const RGBColorf &emit) {
+  _emit = emit;
+  _flags |= F_emit;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::clear_emit
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void EggMaterial::
+clear_emit() {
+  _flags &= ~F_emit;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::has_emit
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool EggMaterial::
+has_emit() const {
+  return (_flags & F_emit) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::get_emit
+//       Access: Public
+//  Description: It is legal to call this even if has_emit() returns
+//               false.  If so, it simply returns the default emit
+//               color.
+////////////////////////////////////////////////////////////////////
+INLINE RGBColorf EggMaterial::
+get_emit() const {
+  if (has_emit()) {
+    return _emit;
+  } else {
+    return RGBColorf(1.0, 1.0, 1.0);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::set_spec
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void EggMaterial::
+set_spec(const RGBColorf &spec) {
+  _spec = spec;
+  _flags |= F_spec;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::clear_spec
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void EggMaterial::
+clear_spec() {
+  _flags &= ~F_spec;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::has_spec
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool EggMaterial::
+has_spec() const {
+  return (_flags & F_spec) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMaterial::get_spec
+//       Access: Public
+//  Description: It is legal to call this even if has_spec() returns
+//               false.  If so, it simply returns the default spec
+//               color.
+////////////////////////////////////////////////////////////////////
+INLINE RGBColorf EggMaterial::
+get_spec() const {
+  if (has_spec()) {
+    return _spec;
+  } else {
+    return RGBColorf(1.0, 1.0, 1.0);
   }
   }
 }
 }

+ 4 - 4
panda/src/egg/eggMaterial.cxx

@@ -19,8 +19,7 @@ EggMaterial::
 EggMaterial(const string &mref_name)
 EggMaterial(const string &mref_name)
   : EggNode(mref_name)
   : EggNode(mref_name)
 {
 {
-  _diff.set(1.0, 1.0, 1.0, 1.0);
-  _has_diff = false;
+  _flags = 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -31,8 +30,9 @@ EggMaterial(const string &mref_name)
 EggMaterial::
 EggMaterial::
 EggMaterial(const EggMaterial &copy) 
 EggMaterial(const EggMaterial &copy) 
   : EggNode(copy),
   : EggNode(copy),
-    _has_diff(copy._has_diff),
-    _diff(copy._diff) {
+    _diff(copy._diff),
+    _flags(copy._flags)
+{
 }
 }
 
 
 
 

+ 29 - 4
panda/src/egg/eggMaterial.h

@@ -23,14 +23,39 @@ public:
 
 
   virtual void write(ostream &out, int indent_level) const;
   virtual void write(ostream &out, int indent_level) const;
 
 
-  INLINE void set_diff(const Colorf &diff);
+  INLINE void set_diff(const RGBColorf &diff);
   INLINE void clear_diff();
   INLINE void clear_diff();
   INLINE bool has_diff() const;
   INLINE bool has_diff() const;
-  INLINE Colorf get_diff() const;
+  INLINE RGBColorf get_diff() const;
+
+  INLINE void set_amb(const RGBColorf &amb);
+  INLINE void clear_amb();
+  INLINE bool has_amb() const;
+  INLINE RGBColorf get_amb() const;
+
+  INLINE void set_emit(const RGBColorf &emit);
+  INLINE void clear_emit();
+  INLINE bool has_emit() const;
+  INLINE RGBColorf get_emit() const;
+
+  INLINE void set_spec(const RGBColorf &spec);
+  INLINE void clear_spec();
+  INLINE bool has_spec() const;
+  INLINE RGBColorf get_spec() const;
 
 
 private:
 private:
-  bool _has_diff;
-  Colorf _diff;
+  enum Flags {
+    F_diff    = 0x001,
+    F_amb     = 0x002,
+    F_emit    = 0x004,
+    F_spec    = 0x008
+  };
+
+  RGBColorf _diff;
+  RGBColorf _amb;
+  RGBColorf _emit;
+  RGBColorf _spec;
+  int _flags;
 
 
 
 
 public:
 public:

+ 43 - 3
panda/src/egg/parser.yxx

@@ -465,17 +465,57 @@ material_body:
   double value = $<_number>5;
   double value = $<_number>5;
 
 
   if (cmp_nocase_uh(name, "diffr") == 0) {
   if (cmp_nocase_uh(name, "diffr") == 0) {
-    Colorf diff = material->get_diff();
+    RGBColorf diff = material->get_diff();
     diff[0] = value;
     diff[0] = value;
     material->set_diff(diff);
     material->set_diff(diff);
   } else if (cmp_nocase_uh(name, "diffg") == 0) {
   } else if (cmp_nocase_uh(name, "diffg") == 0) {
-    Colorf diff = material->get_diff();
+    RGBColorf diff = material->get_diff();
     diff[1] = value;
     diff[1] = value;
     material->set_diff(diff);
     material->set_diff(diff);
   } else if (cmp_nocase_uh(name, "diffb") == 0) {
   } else if (cmp_nocase_uh(name, "diffb") == 0) {
-    Colorf diff = material->get_diff();
+    RGBColorf diff = material->get_diff();
     diff[2] = value;
     diff[2] = value;
     material->set_diff(diff);
     material->set_diff(diff);
+
+  } else if (cmp_nocase_uh(name, "ambr") == 0) {
+    RGBColorf amb = material->get_amb();
+    amb[0] = value;
+    material->set_amb(amb);
+  } else if (cmp_nocase_uh(name, "ambg") == 0) {
+    RGBColorf amb = material->get_amb();
+    amb[1] = value;
+    material->set_amb(amb);
+  } else if (cmp_nocase_uh(name, "ambb") == 0) {
+    RGBColorf amb = material->get_amb();
+    amb[2] = value;
+    material->set_amb(amb);
+
+  } else if (cmp_nocase_uh(name, "emitr") == 0) {
+    RGBColorf emit = material->get_emit();
+    emit[0] = value;
+    material->set_emit(emit);
+  } else if (cmp_nocase_uh(name, "emitg") == 0) {
+    RGBColorf emit = material->get_emit();
+    emit[1] = value;
+    material->set_emit(emit);
+  } else if (cmp_nocase_uh(name, "emitb") == 0) {
+    RGBColorf emit = material->get_emit();
+    emit[2] = value;
+    material->set_emit(emit);
+
+  } else if (cmp_nocase_uh(name, "specr") == 0) {
+    RGBColorf spec = material->get_spec();
+    spec[0] = value;
+    material->set_spec(spec);
+  } else if (cmp_nocase_uh(name, "specg") == 0) {
+    RGBColorf spec = material->get_spec();
+    spec[1] = value;
+    material->set_spec(spec);
+  } else if (cmp_nocase_uh(name, "specb") == 0) {
+    RGBColorf spec = material->get_spec();
+    spec[2] = value;
+    material->set_spec(spec);
+
   } else {
   } else {
     eggyywarning("Unsupported material scalar: " + name);
     eggyywarning("Unsupported material scalar: " + name);
   }
   }

+ 0 - 144
panda/src/glgsg/glGraphicsStateGuardian.I

@@ -253,125 +253,6 @@ call_glLightModelTwoSide(GLboolean twoside)
   }
   }
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::call_glMaterialAmbient
-//       Access:
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GLGraphicsStateGuardian::
-call_glMaterialAmbient( bool twoside, const Colorf& color )
-{
-  if (_material_ambient != color) {
-    _material_ambient = color;
-    if (twoside) {
-#ifdef GSG_VERBOSE
-      glgsg_cat.debug()
-	<< "glMaterial(GL_FRONT_AND_BACK, GL_AMBIENT, "
-	<< color << ")" << endl;
-#endif
-      glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, color.get_data() );
-    } else {
-#ifdef GSG_VERBOSE
-      glgsg_cat.debug()
-	<< "glMaterial(GL_FRONT, GL_AMBIENT, " << color << ")" << endl;
-#endif
-      glMaterialfv( GL_FRONT, GL_AMBIENT, color.get_data() );
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::call_glMaterialDiffuse
-//       Access:
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GLGraphicsStateGuardian::
-call_glMaterialDiffuse( bool twoside, const Colorf& color )
-{
-    if ( _material_diffuse != color )
-    {   
-        _material_diffuse = color;
-	if ( twoside )
-            glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, color.get_data() );
-	else
-            glMaterialfv( GL_FRONT, GL_DIFFUSE, color.get_data() );
-    }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::call_glMaterialAmbientDiffuse
-//       Access:
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GLGraphicsStateGuardian::
-call_glMaterialAmbientDiffuse( bool twoside, const Colorf& color )
-{
-    if ( _material_ambient != color || _material_diffuse != color )
-    {   
-        _material_ambient = color;
-        _material_diffuse = color;
-	if ( twoside )
-            glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, 
-				color.get_data() );
-	else
-            glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color.get_data() );
-    }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::call_glMaterialSpecular
-//       Access:
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GLGraphicsStateGuardian::
-call_glMaterialSpecular( bool twoside, const Colorf& color )
-{
-    if ( _material_specular != color )
-    {   
-        _material_specular = color;
-	if ( twoside )
-            glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, color.get_data() );
-	else
-            glMaterialfv( GL_FRONT, GL_SPECULAR, color.get_data() );
-    }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::call_glMaterialShininess
-//       Access:
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GLGraphicsStateGuardian::
-call_glMaterialShininess( bool twoside, float shininess )
-{
-    if ( _material_shininess != shininess )
-    {   
-        _material_shininess = shininess;
-	if ( twoside )
-            glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, shininess );
-	else
-            glMaterialf( GL_FRONT, GL_SHININESS, shininess );
-    }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::call_glMaterialEmision
-//       Access:
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GLGraphicsStateGuardian::
-call_glMaterialEmission( bool twoside, const Colorf& color )
-{
-    if ( _material_emission != color )
-    {   
-        _material_emission = color;
-	if ( twoside )
-            glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, color.get_data() );
-	else
-            glMaterialfv( GL_FRONT, GL_EMISSION, color.get_data() );
-    }
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glStencilFunc
 //     Function: GLGraphicsStateGuardian::call_glStencilFunc
 //       Access:
 //       Access:
@@ -1002,31 +883,6 @@ INLINE void GLGraphicsStateGuardian::enable_light(int light, bool val)
     }
     }
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::enable_color_material
-//       Access:
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GLGraphicsStateGuardian::
-enable_color_material(bool val) {
-  if (_color_material_enabled != val) {
-    _color_material_enabled = val;
-    if (val) {
-#ifdef GSG_VERBOSE
-      glgsg_cat.debug()
-	<< "glEnable(GL_COLOR_MATERIAL)" << endl;
-#endif
-      glEnable(GL_COLOR_MATERIAL);
-    } else {
-#ifdef GSG_VERBOSE
-      glgsg_cat.debug()
-	<< "glDisable(GL_COLOR_MATERIAL)" << endl;
-#endif
-      glDisable(GL_COLOR_MATERIAL);
-    }
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::enable_texturing
 //     Function: GLGraphicsStateGuardian::enable_texturing
 //       Access:
 //       Access:

+ 39 - 19
panda/src/glgsg/glGraphicsStateGuardian.cxx

@@ -248,7 +248,6 @@ reset() {
   _multisample_enabled = false;
   _multisample_enabled = false;
   _line_smooth_enabled = false;
   _line_smooth_enabled = false;
   _point_smooth_enabled = false;
   _point_smooth_enabled = false;
-  _color_material_enabled = false;
   _scissor_enabled = false;
   _scissor_enabled = false;
   _lighting_enabled = false;
   _lighting_enabled = false;
   _normals_enabled = false;
   _normals_enabled = false;
@@ -2081,7 +2080,6 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
 
 
   set_state(state, false);
   set_state(state, false);
 
 
-  enable_color_material(false);
   set_unpack_alignment(1);
   set_unpack_alignment(1);
 
 
   glMatrixMode( GL_PROJECTION );
   glMatrixMode( GL_PROJECTION );
@@ -2153,19 +2151,43 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void GLGraphicsStateGuardian::apply_material( Material* material )
-{
-    call_glMaterialAmbient( material->get_twoside(), material->get_ambient() );
-    call_glMaterialDiffuse( material->get_twoside(), material->get_diffuse() );
-    call_glMaterialSpecular( material->get_twoside(), 
-            material->get_specular() );
-    call_glMaterialShininess( material->get_twoside(), 
-            material->get_shininess() );
-    call_glMaterialEmission( material->get_twoside(), 
-            material->get_emission() );
+void GLGraphicsStateGuardian::apply_material(const Material *material) {
+  GLenum face = material->get_twoside() ? GL_FRONT_AND_BACK : GL_FRONT;
+  
+  if (material->has_ambient() && material->has_diffuse()) {
+    // The material has both an ambient and diffuse specified.  This
+    // means we do not need glMaterialColor().
+    glMaterialfv(face, GL_AMBIENT, material->get_ambient().get_data());
+    glMaterialfv(face, GL_DIFFUSE, material->get_diffuse().get_data());
+    glDisable(GL_COLOR_MATERIAL);
+
+  } else if (material->has_ambient()) {
+    // The material specifies an ambient, but not a diffuse component.
+    // The diffuse component comes from the object's color.
+    glMaterialfv(face, GL_AMBIENT, material->get_ambient().get_data());
+    glColorMaterial(face, GL_DIFFUSE);
+    glEnable(GL_COLOR_MATERIAL);
+
+  } else if (material->has_diffuse()) {
+    // The material specifies a diffuse, but not an ambient component.
+    // The ambient component comes from the object's color.
+    glMaterialfv(face, GL_AMBIENT, material->get_ambient().get_data());
+    glColorMaterial(face, GL_AMBIENT);
+    glEnable(GL_COLOR_MATERIAL);
+
+  } else {
+    // The material specifies neither a diffuse nor an ambient
+    // component.  Both components come from the object's color.
+    glColorMaterial(face, GL_AMBIENT_AND_DIFFUSE);
+    glEnable(GL_COLOR_MATERIAL);
+  }
+
+  glMaterialfv(face, GL_SPECULAR, material->get_specular().get_data());
+  glMaterialfv(face, GL_EMISSION, material->get_emission().get_data());
+  glMaterialf(face, GL_SHININESS, material->get_shininess());
   
   
-    call_glLightModelLocal( material->get_local() );
-    call_glLightModelTwoSide( material->get_twoside() );
+  call_glLightModelLocal(material->get_local());
+  call_glLightModelTwoSide(material->get_twoside());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -2563,9 +2585,9 @@ void GLGraphicsStateGuardian::
 issue_material(const MaterialAttribute *attrib) {
 issue_material(const MaterialAttribute *attrib) {
   //  activate();
   //  activate();
   if (attrib->is_on()) {
   if (attrib->is_on()) {
-    Material *material = attrib->get_material();
-    nassertv(material != (Material *)NULL);
-    material->apply(this);
+    const Material *material = attrib->get_material();
+    nassertv(material != (const Material *)NULL);
+    apply_material(material);
   }
   }
 }
 }
 
 
@@ -2707,10 +2729,8 @@ void GLGraphicsStateGuardian::issue_light(const LightAttribute *attrib )
   // If no lights were enabled, disable lighting
   // If no lights were enabled, disable lighting
   if (num_enabled == 0) {
   if (num_enabled == 0) {
     enable_lighting(false);
     enable_lighting(false);
-    enable_color_material(false);
   } else {
   } else {
     call_glLightModelAmbient(_cur_ambient_light);
     call_glLightModelAmbient(_cur_ambient_light);
-    enable_color_material(true);
   }
   }
 }
 }
 
 

+ 1 - 9
panda/src/glgsg/glGraphicsStateGuardian.h

@@ -108,7 +108,7 @@ public:
                                  const RenderBuffer &rb,
                                  const RenderBuffer &rb,
 				 const NodeAttributes& na=NodeAttributes());
 				 const NodeAttributes& na=NodeAttributes());
 
 
-  virtual void apply_material(Material* material);
+  virtual void apply_material(const Material *material);
   virtual void apply_fog(Fog *fog);
   virtual void apply_fog(Fog *fog);
 
 
   virtual void apply_light(PointLight* light);
   virtual void apply_light(PointLight* light);
@@ -184,12 +184,6 @@ protected:
   INLINE void call_glLightModelAmbient(const Colorf& color);
   INLINE void call_glLightModelAmbient(const Colorf& color);
   INLINE void call_glLightModelLocal(GLboolean local);
   INLINE void call_glLightModelLocal(GLboolean local);
   INLINE void call_glLightModelTwoSide(GLboolean twoside);
   INLINE void call_glLightModelTwoSide(GLboolean twoside);
-  INLINE void call_glMaterialAmbient(bool twoside, const Colorf& color);
-  INLINE void call_glMaterialDiffuse(bool twoside, const Colorf& color);
-  INLINE void call_glMaterialAmbientDiffuse(bool twoside, const Colorf& color);
-  INLINE void call_glMaterialSpecular(bool twoside, const Colorf& color);
-  INLINE void call_glMaterialShininess(bool twoside, float shininess);
-  INLINE void call_glMaterialEmission(bool twoside, const Colorf& color);
   INLINE void call_glStencilFunc(GLenum func);
   INLINE void call_glStencilFunc(GLenum func);
   INLINE void call_glStencilOp(GLenum op);
   INLINE void call_glStencilOp(GLenum op);
   INLINE void call_glClipPlane(GLenum plane, const double equation[4]);
   INLINE void call_glClipPlane(GLenum plane, const double equation[4]);
@@ -212,7 +206,6 @@ protected:
   INLINE void enable_point_smooth(bool val);
   INLINE void enable_point_smooth(bool val);
   INLINE void enable_lighting(bool val);
   INLINE void enable_lighting(bool val);
   INLINE void enable_light(int light, bool val);
   INLINE void enable_light(int light, bool val);
-  INLINE void enable_color_material(bool val);
   INLINE void enable_texturing(bool val);
   INLINE void enable_texturing(bool val);
   INLINE void enable_scissor(bool val);
   INLINE void enable_scissor(bool val);
   INLINE void enable_dither(bool val);
   INLINE void enable_dither(bool val);
@@ -300,7 +293,6 @@ protected:
   bool _line_smooth_enabled;
   bool _line_smooth_enabled;
   bool _point_smooth_enabled;
   bool _point_smooth_enabled;
   bool* _light_enabled;      // bool[_max_lights]
   bool* _light_enabled;      // bool[_max_lights]
-  bool _color_material_enabled;
   bool _scissor_enabled;
   bool _scissor_enabled;
   bool _lighting_enabled;
   bool _lighting_enabled;
   bool _texturing_enabled;
   bool _texturing_enabled;

+ 4 - 1
panda/src/gobj/Sources.pp

@@ -15,7 +15,9 @@
     geomSprite.cxx geomSprite.h geomTri.cxx geomTri.h geomTrifan.cxx \
     geomSprite.cxx geomSprite.h geomTri.cxx geomTri.h geomTrifan.cxx \
     geomTrifan.h geomTristrip.cxx geomTristrip.h \
     geomTrifan.h geomTristrip.cxx geomTristrip.h \
     imageBuffer.I imageBuffer.cxx \
     imageBuffer.I imageBuffer.cxx \
-    imageBuffer.h material.I material.cxx material.h orthoProjection.I \
+    imageBuffer.h material.I material.cxx material.h \
+    materialPool.I materialPool.h materialPool.cxx \
+    orthoProjection.I \
     orthoProjection.cxx orthoProjection.h perspectiveProjection.I \
     orthoProjection.cxx orthoProjection.h perspectiveProjection.I \
     perspectiveProjection.cxx perspectiveProjection.h pixelBuffer.I \
     perspectiveProjection.cxx perspectiveProjection.h pixelBuffer.I \
     pixelBuffer.N pixelBuffer.cxx pixelBuffer.h projection.cxx \
     pixelBuffer.N pixelBuffer.cxx pixelBuffer.h projection.cxx \
@@ -28,6 +30,7 @@
     geomLinestrip.h geomPoint.h geomPolygon.h geomQuad.h geomSphere.h \
     geomLinestrip.h geomPoint.h geomPolygon.h geomQuad.h geomSphere.h \
     geomSprite.I geomSprite.h geomTri.h geomTrifan.h geomTristrip.h \
     geomSprite.I geomSprite.h geomTri.h geomTrifan.h geomTristrip.h \
     geomprimitives.h imageBuffer.I imageBuffer.h material.I material.h \
     geomprimitives.h imageBuffer.I imageBuffer.h material.I material.h \
+    materialPool.I materialPool.h \
     orthoProjection.I orthoProjection.h perspectiveProjection.I \
     orthoProjection.I orthoProjection.h perspectiveProjection.I \
     perspectiveProjection.h pixelBuffer.I pixelBuffer.h projection.h \
     perspectiveProjection.h pixelBuffer.I pixelBuffer.h projection.h \
     texture.I texture.h texturePool.I texturePool.h
     texture.I texture.h texturePool.I texturePool.h

+ 1 - 0
panda/src/gobj/config_gobj.cxx

@@ -150,5 +150,6 @@ ConfigureFn(config_gobj) {
   GeomTristrip::register_with_read_factory();
   GeomTristrip::register_with_read_factory();
   GeomTrifan::register_with_read_factory();
   GeomTrifan::register_with_read_factory();
   GeomSphere::register_with_read_factory();
   GeomSphere::register_with_read_factory();
+  Material::register_with_read_factory();
   Texture::register_with_read_factory();
   Texture::register_with_read_factory();
 }
 }

+ 248 - 54
panda/src/gobj/material.I

@@ -5,103 +5,267 @@
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Material::get_ambient 
+//     Function: Material::Constructor
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE Colorf Material::get_ambient( void ) const
-{
-    return _ambient;
+INLINE Material::
+Material() {
+  _flags = 0;
+  _shininess = 0.0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Material::set_ambient
+//     Function: Material::Copy Constructor
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void Material::set_ambient( const Colorf& color )
-{
-    _ambient = color;
+INLINE Material::
+Material(const Material &copy) {
+  operator = (copy);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Material::get_diffuse
+//     Function: Material::Destructor 
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE Colorf Material::get_diffuse( void ) const
-{
-    return _diffuse;
+INLINE Material::
+~Material() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::has_ambient 
+//       Access: Public
+//  Description: Returns true if the ambient color has been explicitly
+//               set for this material, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Material::
+has_ambient() const {
+  return (_flags & F_ambient) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::get_ambient 
+//       Access: Public
+//  Description: Returns the ambient color setting, if it has been
+//               set.  Returns (0,0,0,0) if the ambient color has not
+//               been set.
+////////////////////////////////////////////////////////////////////
+INLINE const Colorf &Material::
+get_ambient() const {
+  return (_flags & F_ambient) != 0 ? _ambient : Colorf::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::set_ambient
+//       Access: Public
+//  Description: Specifies the ambient color setting of the material.
+//               This will be the multiplied by any ambient lights in
+//               effect on the material to set its base color.
+//
+//               This is the color of the object as it appears in the
+//               absence of direct light.
+//
+//               If this is not set, the object color will be used.
+////////////////////////////////////////////////////////////////////
+INLINE void Material::
+set_ambient(const Colorf &color) {
+  _ambient = color;
+  _flags |= F_ambient;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::clear_ambient
+//       Access: Public
+//  Description: Removes the explicit ambient color from the material.
+////////////////////////////////////////////////////////////////////
+INLINE void Material::
+clear_ambient() {
+  _flags &= ~F_ambient;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::has_diffuse 
+//       Access: Public
+//  Description: Returns true if the diffuse color has been explicitly
+//               set for this material, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Material::
+has_diffuse() const {
+  return (_flags & F_diffuse) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::get_diffuse
+//       Access: Public
+//  Description: Returns the diffuse color setting, if it has been
+//               set.  Returns (0,0,0,0) if the diffuse color has not
+//               been set.
+////////////////////////////////////////////////////////////////////
+INLINE const Colorf &Material::
+get_diffuse() const {
+  return (_flags & F_diffuse) != 0 ? _diffuse : Colorf::zero();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Material::set_diffuse
 //     Function: Material::set_diffuse
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Specifies the diffuse color setting of the material.
+//               This will be multiplied by any lights in effect on
+//               the material to get the color in the parts of the
+//               object illuminated by the lights.
+//
+//               This is the primary color of an object; the color of
+//               the object as it appears in direct light, in the
+//               absence of highlights.
+//
+//               If this is not set, the object color will be used.
+////////////////////////////////////////////////////////////////////
+INLINE void Material::
+set_diffuse(const Colorf &color) {
+  _diffuse = color;
+  _flags |= F_diffuse;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::clear_diffuse
+//       Access: Public
+//  Description: Removes the explicit diffuse color from the material.
+////////////////////////////////////////////////////////////////////
+INLINE void Material::
+clear_diffuse() {
+  _flags &= ~F_diffuse;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void Material::set_diffuse( const Colorf& color )
-{
-    _diffuse = color;
+//     Function: Material::has_specular 
+//       Access: Public
+//  Description: Returns true if the specular color has been explicitly
+//               set for this material, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Material::
+has_specular() const {
+  return (_flags & F_specular) != 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Material::get_specular
 //     Function: Material::get_specular
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Returns the specular color setting, if it has been
+//               set.  Returns (0,0,0,0) if the specular color has not
+//               been set.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE Colorf Material::get_specular( void ) const
-{
-    return _specular;
+INLINE const Colorf &Material::
+get_specular() const {
+  return (_flags & F_specular) != 0 ? _specular : Colorf::zero();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Material::set_specular
 //     Function: Material::set_specular
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Specifies the diffuse color setting of the material.
+//               This will be multiplied by any lights in effect on
+//               the material to compute the color of specular
+//               highlights on the object.
+//
+//               This is the highlight color of an object: the color
+//               of small highlight reflections.
+//
+//               If this is not set, highlights will not appear.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void Material::set_specular( const Colorf& color )
-{
-    _specular = color;
+INLINE void Material::
+set_specular(const Colorf &color) {
+  _specular = color;
+  _flags |= F_specular;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Material::get_shininess
+//     Function: Material::clear_specular
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Removes the explicit specular color from the material.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE float Material::get_shininess( void ) const
-{
-    return _shininess;
+INLINE void Material::
+clear_specular() {
+  _flags &= ~F_specular;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Material::set_shininess
+//     Function: Material::has_emission 
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Returns true if the emission color has been explicitly
+//               set for this material, false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void Material::set_shininess( float shininess )
-{
-    _shininess = shininess;
+INLINE bool Material::
+has_emission() const {
+  return (_flags & F_emission) != 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Material::get_emission
 //     Function: Material::get_emission
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Returns the emmission color setting, if it has been
+//               set.  Returns (0,0,0,0) if the emmission color has not
+//               been set.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE Colorf Material::get_emission( void ) const
-{
-    return _emission;
+INLINE const Colorf &Material::
+get_emission() const {
+  return (_flags & F_emission) != 0 ? _emission : Colorf::zero();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Material::set_emission
 //     Function: Material::set_emission
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Specifies the emission color setting of the material.
+//               This is the color of the object as it appears in the
+//               absence of any light whatsover, including ambient
+//               light.  It is as if the object is glowing by this
+//               color (although of course it will not illuminate
+//               neighboring objects).
+//
+//               If this is not set, the object will not glow by its
+//               own light and will only appear visible in the
+//               presence of one or more lights.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void Material::set_emission( const Colorf& color )
-{
-    _emission = color;
+INLINE void Material::
+set_emission(const Colorf &color) {
+  _emission = color;
+  _flags |= F_emission;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::clear_emission
+//       Access: Public
+//  Description: Removes the explicit emission color from the material.
+////////////////////////////////////////////////////////////////////
+INLINE void Material::
+clear_emission() {
+  _flags &= ~F_emission;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::get_shininess
+//       Access: Public
+//  Description: Returns the shininess exponent of the material.
+////////////////////////////////////////////////////////////////////
+INLINE float Material::
+get_shininess() const {
+  return _shininess;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::set_shininess
+//       Access: Public
+//  Description: Sets the shininess exponent of the material.  This
+//               controls the size of the specular highlight spot.  In
+//               general, larger number produce a smaller specular
+//               highlight, which makes the object appear shinier.
+//               Smaller numbers produce a larger highlight, which
+//               makes the object appear less shiny.
+////////////////////////////////////////////////////////////////////
+INLINE void Material::
+set_shininess(float shininess) {
+  _shininess = shininess;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -109,9 +273,9 @@ INLINE void Material::set_emission( const Colorf& color )
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE bool Material::get_local( void ) const
-{
-    return _local;
+INLINE bool Material::
+get_local() const {
+  return (_flags & F_local) != 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -119,9 +283,9 @@ INLINE bool Material::get_local( void ) const
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void Material::set_local( bool local )
-{
-    _local = local;
+INLINE void Material::
+set_local(bool local) {
+  _flags |= F_local;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -129,9 +293,9 @@ INLINE void Material::set_local( bool local )
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE bool Material::get_twoside( void ) const
-{
-    return _twoside;
+INLINE bool Material::
+get_twoside() const {
+  return (_flags & F_twoside) != 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -139,7 +303,37 @@ INLINE bool Material::get_twoside( void ) const
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void Material::set_twoside( bool twoside )
-{
-    _twoside = twoside;
+INLINE void Material::
+set_twoside(bool twoside) {
+  _flags = F_twoside;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::operator ==
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool Material::
+operator == (const Material &other) const {
+  return compare_to(other) == 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::operator !=
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool Material::
+operator != (const Material &other) const {
+  return compare_to(other) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::operator <
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool Material::
+operator < (const Material &other) const {
+  return compare_to(other) < 0;
 }
 }

+ 127 - 41
panda/src/gobj/material.cxx

@@ -2,14 +2,15 @@
 // Created by:  mike (09Jan97)
 // Created by:  mike (09Jan97)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//
-////////////////////////////////////////////////////////////////////
-// Includes
-////////////////////////////////////////////////////////////////////
+
 #include <pandabase.h>
 #include <pandabase.h>
 #include "material.h"
 #include "material.h"
 
 
 #include <indent.h>
 #include <indent.h>
+#include <datagram.h>
+#include <datagramIterator.h>
+#include <bamReader.h>
+#include <bamWriter.h>
 
 
 #include <stddef.h>
 #include <stddef.h>
 
 
@@ -19,57 +20,142 @@
 TypeHandle Material::_type_handle;
 TypeHandle Material::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Constructor
-//       Access:
-//  Description:
+//     Function: Material::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void Material::
+operator = (const Material &copy) {
+  _ambient = copy._ambient;
+  _diffuse = copy._diffuse;
+  _specular = copy._specular;
+  _emission = copy._emission;
+  _shininess = copy._shininess;
+  _flags = copy._flags;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::compare_to
+//       Access: Public
+//  Description: Returns a number less than zero if this material
+//               sorts before the other one, greater than zero if it
+//               sorts after, or zero if they are equivalent.  The
+//               sorting order is arbitrary and largely meaningless,
+//               except to differentiate different materials.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-Material::Material( void )
-{
-    set_ambient( Colorf( 0.2, 0.2, 0.2, 1 ) );
-    set_diffuse( Colorf( 0.8, 0.8, 0.8, 1 ) );
-    set_specular( Colorf( 0, 0, 0, 1 ) );
-    set_shininess( 0.0 );
-    set_emission( Colorf( 0, 0, 0, 1 ) );
+int Material::
+compare_to(const Material &other) const {
+  if (_flags != other._flags) {
+    return _flags - other._flags;
+  }
+  if (has_ambient() && get_ambient() != other.get_ambient()) {
+    return get_ambient().compare_to(other.get_ambient());
+  }
+  if (has_diffuse() && get_diffuse() != other.get_diffuse()) {
+    return get_diffuse().compare_to(other.get_diffuse());
+  }
+  if (has_specular() && get_specular() != other.get_specular()) {
+    return get_specular().compare_to(other.get_specular());
+  }
+  if (has_emission() && get_emission() != other.get_emission()) {
+    return get_emission().compare_to(other.get_emission());
+  }
+  if (get_shininess() != other.get_shininess()) {
+    return get_shininess() < other.get_shininess() ? -1 : 1;
+  }
 
 
-    set_local( false );
-    set_twoside( false );
+  return 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Destructor 
-//       Access:
+//     Function: Material::output 
+//       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-Material::~Material( void )
-{
+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();
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: output 
-//       Access:
+//     Function: Material::write 
+//       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Material::output( ostream &out ) const
-{
-  out << "a" << _ambient[0] << ",d" << _diffuse[0] 
-      << ",s" << _specular[0] << ",s" << _shininess
-      << ",e" << _emission[0] << ",l" << _local
-      << ",t" << _twoside;
+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";
+  indent(out, indent_level) << "shininess = " << get_shininess() << "\n";
+  indent(out, indent_level) << "local = " << get_local() << "\n";
+  indent(out, indent_level) << "twoside = " << get_twoside() << "\n";
 }
 }
 
 
+
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: write 
-//       Access:
-//  Description:
+//     Function: Material::register_with_read_factory
+//       Access: Public, Static
+//  Description: Factory method to generate a Material object
+////////////////////////////////////////////////////////////////////
+void Material::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_Material);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::write_datagram
+//       Access: Public
+//  Description: Function to write the important information in
+//               the particular object to a Datagram
+////////////////////////////////////////////////////////////////////
+void Material::
+write_datagram(BamWriter *manager, Datagram &me) {
+  _ambient.write_datagram(me);
+  _diffuse.write_datagram(me);
+  _specular.write_datagram(me);
+  _emission.write_datagram(me);
+  me.add_float32(_shininess);
+  me.add_int32(_flags);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::make_Material
+//       Access: Protected
+//  Description: Factory method to generate a Material object
+////////////////////////////////////////////////////////////////////
+TypedWriteable *Material::
+make_Material(const FactoryParams &params) {
+  Material *me = new Material;
+  BamReader *manager;
+  Datagram packet;
+
+  parse_params(params, manager, packet);
+  DatagramIterator scan(packet);
+
+  me->fillin(scan, manager);
+  return me;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Material::fillin
+//       Access: Protected
+//  Description: Function that reads out of the datagram (or asks
+//               manager to read) all of the data that is needed to
+//               re-create this object and stores it in the appropiate
+//               place
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Material::write( ostream &out, int indent_level ) const
-{
-  indent(out, indent_level) << "ambient = " << _ambient << "\n";
-  indent(out, indent_level) << "diffuse = " << _diffuse << "\n";
-  indent(out, indent_level) << "specular = " << _specular << "\n";
-  indent(out, indent_level) << "shininess = " << _shininess << "\n";
-  indent(out, indent_level) << "emission = " << _emission << "\n";
-  indent(out, indent_level) << "local = " << _local << "\n";
-  indent(out, indent_level) << "twoside = " << _twoside << "\n";
+void Material::
+fillin(DatagramIterator& scan, BamReader* manager) {
+  _ambient.read_datagram(scan);
+  _diffuse.read_datagram(scan);
+  _specular.read_datagram(scan);
+  _emission.read_datagram(scan);
+  _shininess = scan.get_float32();
+  _flags = scan.get_int32();
 }
 }

+ 73 - 49
panda/src/gobj/material.h

@@ -11,68 +11,92 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 #include <pandabase.h>
 #include <pandabase.h>
 
 
-#include <graphicsStateGuardianBase.h>
-#include <typedReferenceCount.h>
+#include <typedWriteableReferenceCount.h>
 #include <luse.h>
 #include <luse.h>
 
 
-////////////////////////////////////////////////////////////////////
-// Defines
-////////////////////////////////////////////////////////////////////
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : Material
 //       Class : Material
-// Description :
+// Description : Defines the way an object appears in the presence of
+//               lighting.  A material is only necessary if lighting
+//               is to be enabled; otherwise, the material isn't used.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA Material : public TypedReferenceCount
-{
-    public:
-
-	Material( void );
-	~Material( void );
-
-  	void apply( GraphicsStateGuardianBase *gsg ) {
-	    gsg->apply_material( this );
-	}
-
-	INLINE Colorf get_ambient( void ) const;
-	INLINE void set_ambient( const Colorf& color );
-	INLINE Colorf get_diffuse( void ) const;
-	INLINE void set_diffuse( const Colorf& color );
-	INLINE Colorf get_specular( void ) const;
-	INLINE void set_specular( const Colorf& color );
-	INLINE float get_shininess( void ) const;
-	INLINE void set_shininess( float shininess );
-	INLINE Colorf get_emission( void ) const;
-	INLINE void set_emission( const Colorf& color );
-
-	INLINE bool get_local( void ) const;
-	INLINE void set_local( bool local );
-	INLINE bool get_twoside( void ) const;
-	INLINE void set_twoside( bool twoside );
-
-	void output( ostream &out ) const;
-	void write( ostream &out, int indent = 0 ) const;
-
-    protected:
-
-	Colorf				_ambient;
-	Colorf				_diffuse;
-	Colorf				_specular;
-	float				_shininess;
-	Colorf				_emission;
-
-	bool				_local;
-	bool				_twoside;
+class EXPCL_PANDA Material : public TypedWriteableReferenceCount {
+PUBLISHED:
+  INLINE Material();
+  INLINE Material(const Material &copy);
+  void operator = (const Material &copy);
+  INLINE ~Material();
+
+  INLINE bool has_ambient() const;
+  INLINE const Colorf &get_ambient() const;
+  INLINE void set_ambient(const Colorf &color);
+  INLINE void clear_ambient();
+
+  INLINE bool has_diffuse() const;
+  INLINE const Colorf &get_diffuse() const;
+  INLINE void set_diffuse(const Colorf &color);
+  INLINE void clear_diffuse();
+
+  INLINE bool has_specular() const;
+  INLINE const Colorf &get_specular() const;
+  INLINE void set_specular(const Colorf &color);
+  INLINE void clear_specular();
+
+  INLINE bool has_emission() const;
+  INLINE const Colorf &get_emission() const;
+  INLINE void set_emission(const Colorf &color);
+  INLINE void clear_emission();
+
+  INLINE float get_shininess() const;
+  INLINE void set_shininess(float shininess);
+  
+  INLINE bool get_local() const;
+  INLINE void set_local(bool local);
+  INLINE bool get_twoside() const;
+  INLINE void set_twoside(bool twoside);
+
+  INLINE bool operator == (const Material &other) const;
+  INLINE bool operator != (const Material &other) const;
+  INLINE bool operator < (const Material &other) const;
+
+  int compare_to(const Material &other) const;
+  
+  void output(ostream &out) const;
+  void write(ostream &out, int indent) const;
+
+private:
+  Colorf _ambient;
+  Colorf _diffuse;
+  Colorf _specular;
+  Colorf _emission;
+  float _shininess;
+
+  enum Flags {
+    F_ambient   = 0x001,
+    F_diffuse   = 0x002,
+    F_specular  = 0x004,
+    F_emission  = 0x008,
+    F_local     = 0x010,
+    F_twoside   = 0x020,
+  };
+  int _flags;
 
 
 public:
 public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &me);  
+
+protected:
+  static TypedWriteable *make_Material(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
 
 
+public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedReferenceCount::init_type();
+    TypedWriteableReferenceCount::init_type();
     register_type(_type_handle, "Material",
     register_type(_type_handle, "Material",
-		  TypedReferenceCount::get_class_type());
+		  TypedWriteableReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 1 - 1
panda/src/graph/nodeRelation.cxx

@@ -967,7 +967,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: NodeRelation::register_with_factory
+//     Function: NodeRelation::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static
 //  Description: Factory method to generate a NodeRelation object
 //  Description: Factory method to generate a NodeRelation object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -133,7 +133,7 @@ public:
 				 const RenderBuffer &rb,
 				 const RenderBuffer &rb,
 				 const NodeAttributes& na=NodeAttributes())=0;
 				 const NodeAttributes& na=NodeAttributes())=0;
 
 
-  virtual void apply_material(Material *material)=0;
+  virtual void apply_material(const Material *material)=0;
   virtual void apply_fog(Fog *fog)=0;
   virtual void apply_fog(Fog *fog)=0;
 
 
   virtual void apply_light(PointLight *light)=0;
   virtual void apply_light(PointLight *light)=0;

+ 3 - 3
panda/src/sgattrib/materialAttribute.I

@@ -18,8 +18,8 @@ MaterialAttribute() {
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void MaterialAttribute::
 INLINE void MaterialAttribute::
-set_on(Material *material) {
-  nassertv(material != (Material *)NULL);
+set_on(const Material *material) {
+  nassertv(material != (const Material *)NULL);
   _value = material;
   _value = material;
   OnOffAttribute::set_on();
   OnOffAttribute::set_on();
 }
 }
@@ -31,7 +31,7 @@ set_on(Material *material) {
 //               represents.  It is only valid to call this if is_on()
 //               represents.  It is only valid to call this if is_on()
 //               has returned true.
 //               has returned true.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE PT(Material) MaterialAttribute::
+INLINE const Material *MaterialAttribute::
 get_material() const {
 get_material() const {
   nassertr(is_on(), NULL);
   nassertr(is_on(), NULL);
   return _value;
   return _value;

+ 3 - 3
panda/src/sgattrib/materialAttribute.cxx

@@ -68,7 +68,7 @@ set_value_from(const OnOffTransition *other) {
   const MaterialTransition *ot;
   const MaterialTransition *ot;
   DCAST_INTO_V(ot, other);
   DCAST_INTO_V(ot, other);
   _value = ot->_value;
   _value = ot->_value;
-  nassertv(_value != (Material *)NULL);
+  nassertv(_value != (const Material *)NULL);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -90,7 +90,7 @@ compare_values(const OnOffAttribute *other) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MaterialAttribute::
 void MaterialAttribute::
 output_value(ostream &out) const {
 output_value(ostream &out) const {
-  nassertv(_value != (Material *)NULL);
+  nassertv(_value != (const Material *)NULL);
   out << *_value;
   out << *_value;
 }
 }
 
 
@@ -102,6 +102,6 @@ output_value(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MaterialAttribute::
 void MaterialAttribute::
 write_value(ostream &out, int indent_level) const {
 write_value(ostream &out, int indent_level) const {
-  nassertv(_value != (Material *)NULL);
+  nassertv(_value != (const Material *)NULL);
   indent(out, indent_level) << *_value << "\n";
   indent(out, indent_level) << *_value << "\n";
 }
 }

+ 4 - 3
panda/src/sgattrib/materialAttribute.h

@@ -10,6 +10,7 @@
 
 
 #include <onOffAttribute.h>
 #include <onOffAttribute.h>
 #include <material.h>
 #include <material.h>
+#include <pointerTo.h>
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : MaterialAttribute
 // 	 Class : MaterialAttribute
@@ -19,8 +20,8 @@ class EXPCL_PANDA MaterialAttribute : public OnOffAttribute {
 public:
 public:
   INLINE MaterialAttribute();
   INLINE MaterialAttribute();
 
 
-  INLINE void set_on(Material *material);
-  INLINE PT(Material) get_material() const;
+  INLINE void set_on(const Material *material);
+  INLINE const Material *get_material() const;
 
 
   virtual TypeHandle get_handle() const;
   virtual TypeHandle get_handle() const;
   virtual NodeAttribute *make_copy() const;
   virtual NodeAttribute *make_copy() const;
@@ -34,7 +35,7 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
-  PT(Material) _value;
+  CPT(Material) _value;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 4 - 4
panda/src/sgattrib/materialTransition.I

@@ -18,7 +18,7 @@ MaterialTransition() {
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE MaterialTransition::
 INLINE MaterialTransition::
-MaterialTransition(Material *material) : 
+MaterialTransition(const Material *material) : 
   OnOffTransition(TD_on),
   OnOffTransition(TD_on),
   _value(material)
   _value(material)
 {
 {
@@ -43,8 +43,8 @@ off() {
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void MaterialTransition::
 INLINE void MaterialTransition::
-set_on(Material *material) {
-  nassertv(material != (Material *)NULL);
+set_on(const Material *material) {
+  nassertv(material != (const Material *)NULL);
   _value = material;
   _value = material;
   OnOffTransition::set_on();
   OnOffTransition::set_on();
 }
 }
@@ -56,7 +56,7 @@ set_on(Material *material) {
 //               represents.  It is only valid to call this if is_on()
 //               represents.  It is only valid to call this if is_on()
 //               has returned true.
 //               has returned true.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE PT(Material) MaterialTransition::
+INLINE const Material *MaterialTransition::
 get_material() const {
 get_material() const {
   nassertr(is_on(), NULL);
   nassertr(is_on(), NULL);
   return _value;
   return _value;

+ 87 - 3
panda/src/sgattrib/materialTransition.cxx

@@ -5,8 +5,13 @@
 
 
 #include "materialTransition.h"
 #include "materialTransition.h"
 #include "materialAttribute.h"
 #include "materialAttribute.h"
+#include "config_sgattrib.h"
 
 
 #include <indent.h>
 #include <indent.h>
+#include <datagram.h>
+#include <datagramIterator.h>
+#include <bamReader.h>
+#include <bamWriter.h>
 
 
 TypeHandle MaterialTransition::_type_handle;
 TypeHandle MaterialTransition::_type_handle;
 
 
@@ -42,7 +47,7 @@ set_value_from(const OnOffTransition *other) {
   const MaterialTransition *ot;
   const MaterialTransition *ot;
   DCAST_INTO_V(ot, other);
   DCAST_INTO_V(ot, other);
   _value = ot->_value;
   _value = ot->_value;
-  nassertv(_value != (Material *)NULL);
+  nassertv(_value != (const Material *)NULL);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -64,7 +69,7 @@ compare_values(const OnOffTransition *other) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MaterialTransition::
 void MaterialTransition::
 output_value(ostream &out) const {
 output_value(ostream &out) const {
-  nassertv(_value != (Material *)NULL);
+  nassertv(_value != (const Material *)NULL);
   out << *_value;
   out << *_value;
 }
 }
 
 
@@ -76,6 +81,85 @@ output_value(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MaterialTransition::
 void MaterialTransition::
 write_value(ostream &out, int indent_level) const {
 write_value(ostream &out, int indent_level) const {
-  nassertv(_value != (Material *)NULL);
+  nassertv(_value != (const Material *)NULL);
   indent(out, indent_level) << *_value << "\n";
   indent(out, indent_level) << *_value << "\n";
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: MaterialTransition::register_with_read_factory
+//       Access: Public, Static
+//  Description: Factory method to generate a MaterialTransition object
+////////////////////////////////////////////////////////////////////
+void MaterialTransition::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_MaterialTransition);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MaterialTransition::write_datagram
+//       Access: Public
+//  Description: Function to write the important information in
+//               the particular object to a Datagram
+////////////////////////////////////////////////////////////////////
+void MaterialTransition::
+write_datagram(BamWriter *manager, Datagram &me) {
+  OnOffTransition::write_datagram(manager, me);
+  manager->write_pointer(me, _value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MaterialTransition::complete_pointers
+//       Access: Public
+//  Description: Takes in a vector of pointes to TypedWriteable
+//               objects that correspond to all the requests for 
+//               pointers that this object made to BamReader.
+////////////////////////////////////////////////////////////////////
+int MaterialTransition::
+complete_pointers(vector_typedWriteable &plist, BamReader *) {
+  if (plist[0] == TypedWriteable::Null) {
+    if (sgattrib_cat->is_debug()) {
+      sgattrib_cat->debug()
+	<< get_type().get_name() << " received null Material," 
+	<< " turning off" << endl;
+    }
+    _value = (const Material *)NULL;
+    set_off();
+
+  } else {
+    _value = DCAST(Material, plist[0]);
+  }
+
+  return 1;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MaterialTransition::make_MaterialTransition
+//       Access: Protected
+//  Description: Factory method to generate a MaterialTransition object
+////////////////////////////////////////////////////////////////////
+TypedWriteable* MaterialTransition::
+make_MaterialTransition(const FactoryParams &params) {
+  MaterialTransition *me = new MaterialTransition;
+  BamReader *manager;
+  Datagram packet;
+
+  parse_params(params, manager, packet);
+  DatagramIterator scan(packet);
+
+  me->fillin(scan, manager);
+  return me;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MaterialTransition::fillin
+//       Access: Protected
+//  Description: Function that reads out of the datagram (or asks
+//               manager to read) all of the data that is needed to
+//               re-create this object and stores it in the appropiate
+//               place
+////////////////////////////////////////////////////////////////////
+void MaterialTransition::
+fillin(DatagramIterator& scan, BamReader* manager) {
+  OnOffTransition::fillin(scan, manager);
+  manager->read_pointer(scan, this);
+}

+ 17 - 5
panda/src/sgattrib/materialTransition.h

@@ -10,6 +10,7 @@
 
 
 #include <onOffTransition.h>
 #include <onOffTransition.h>
 #include <material.h>
 #include <material.h>
+#include <pointerTo.h>
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : MaterialTransition
 // 	 Class : MaterialTransition
@@ -19,12 +20,13 @@
 class EXPCL_PANDA MaterialTransition : public OnOffTransition {
 class EXPCL_PANDA MaterialTransition : public OnOffTransition {
 public:
 public:
   INLINE MaterialTransition();
   INLINE MaterialTransition();
-  INLINE MaterialTransition(Material *material);
+  INLINE MaterialTransition(const Material *material);
   INLINE static MaterialTransition off();
   INLINE static MaterialTransition off();
 
 
-  INLINE void set_on(Material *material);
-  INLINE PT(Material) get_material() const;
-  
+  INLINE void set_on(const Material *material);
+  INLINE const Material *get_material() const;
+
+public:  
   virtual NodeTransition *make_copy() const;
   virtual NodeTransition *make_copy() const;
   virtual NodeAttribute *make_attrib() const;
   virtual NodeAttribute *make_attrib() const;
 
 
@@ -34,7 +36,17 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
-  PT(Material) _value;
+  CPT(Material) _value;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &me);  
+  virtual int complete_pointers(vector_typedWriteable &plist, 
+				BamReader *manager);
+
+protected:
+  static TypedWriteable *make_MaterialTransition(const FactoryParams &params);
+  void fillin(DatagramIterator& scan, BamReader* manager);
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 25 - 32
panda/src/sgattrib/textureTransition.cxx

@@ -86,6 +86,16 @@ write_value(ostream &out, int indent_level) const {
   indent(out, indent_level) << *_value << "\n";
   indent(out, indent_level) << *_value << "\n";
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextureTransition::register_with_read_factory
+//       Access: Public, Static
+//  Description: Factory method to generate a TextureTransition object
+////////////////////////////////////////////////////////////////////
+void TextureTransition::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_TextureTransition);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextureTransition::write_datagram
 //     Function: TextureTransition::write_datagram
 //       Access: Public
 //       Access: Public
@@ -93,27 +103,11 @@ write_value(ostream &out, int indent_level) const {
 //               the particular object to a Datagram
 //               the particular object to a Datagram
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TextureTransition::
 void TextureTransition::
-write_datagram(BamWriter *manager, Datagram &me)
-{
+write_datagram(BamWriter *manager, Datagram &me) {
   OnOffTransition::write_datagram(manager, me);
   OnOffTransition::write_datagram(manager, me);
   manager->write_pointer(me, _value);
   manager->write_pointer(me, _value);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: TextureTransition::fillin
-//       Access: Protected
-//  Description: Function that reads out of the datagram (or asks
-//               manager to read) all of the data that is needed to
-//               re-create this object and stores it in the appropiate
-//               place
-////////////////////////////////////////////////////////////////////
-void TextureTransition::
-fillin(DatagramIterator& scan, BamReader* manager)
-{
-  OnOffTransition::fillin(scan, manager);
-  manager->read_pointer(scan, this);
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextureTransition::complete_pointers
 //     Function: TextureTransition::complete_pointers
 //       Access: Public
 //       Access: Public
@@ -122,10 +116,8 @@ fillin(DatagramIterator& scan, BamReader* manager)
 //               pointers that this object made to BamReader.
 //               pointers that this object made to BamReader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int TextureTransition::
 int TextureTransition::
-complete_pointers(vector_typedWriteable &plist, BamReader*)
-{
-  if(plist[0] == TypedWriteable::Null)
-  {
+complete_pointers(vector_typedWriteable &plist, BamReader *) {
+  if (plist[0] == TypedWriteable::Null) {
     if (sgattrib_cat->is_debug()) {
     if (sgattrib_cat->is_debug()) {
       sgattrib_cat->debug()
       sgattrib_cat->debug()
 	<< get_type().get_name() << " received null Texture," 
 	<< get_type().get_name() << " received null Texture," 
@@ -133,9 +125,8 @@ complete_pointers(vector_typedWriteable &plist, BamReader*)
     }
     }
     _value = (Texture *)NULL;
     _value = (Texture *)NULL;
     set_off();
     set_off();
-  }
-  else
-  {
+
+  } else {
     _value = DCAST(Texture, plist[0]);
     _value = DCAST(Texture, plist[0]);
   }
   }
 
 
@@ -148,8 +139,7 @@ complete_pointers(vector_typedWriteable &plist, BamReader*)
 //  Description: Factory method to generate a TextureTransition object
 //  Description: Factory method to generate a TextureTransition object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 TypedWriteable* TextureTransition::
 TypedWriteable* TextureTransition::
-make_TextureTransition(const FactoryParams &params)
-{
+make_TextureTransition(const FactoryParams &params) {
   TextureTransition *me = new TextureTransition;
   TextureTransition *me = new TextureTransition;
   BamReader *manager;
   BamReader *manager;
   Datagram packet;
   Datagram packet;
@@ -162,12 +152,15 @@ make_TextureTransition(const FactoryParams &params)
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: TextureTransition::register_with_factory
-//       Access: Public, Static
-//  Description: Factory method to generate a TextureTransition object
+//     Function: TextureTransition::fillin
+//       Access: Protected
+//  Description: Function that reads out of the datagram (or asks
+//               manager to read) all of the data that is needed to
+//               re-create this object and stores it in the appropiate
+//               place
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TextureTransition::
 void TextureTransition::
-register_with_read_factory(void)
-{
-  BamReader::get_factory()->register_factory(get_class_type(), make_TextureTransition);
+fillin(DatagramIterator& scan, BamReader* manager) {
+  OnOffTransition::fillin(scan, manager);
+  manager->read_pointer(scan, this);
 }
 }

+ 3 - 4
panda/src/sgattrib/textureTransition.h

@@ -51,14 +51,13 @@ protected:
   PT(Texture) _value;
   PT(Texture) _value;
 
 
 public:
 public:
-  static void register_with_read_factory(void);
-  virtual void write_datagram(BamWriter* manager, Datagram &me);  
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &me);  
   virtual int complete_pointers(vector_typedWriteable &plist, 
   virtual int complete_pointers(vector_typedWriteable &plist, 
 				BamReader *manager);
 				BamReader *manager);
 
 
-  static TypedWriteable *make_TextureTransition(const FactoryParams &params);
-
 protected:
 protected:
+  static TypedWriteable *make_TextureTransition(const FactoryParams &params);
   void fillin(DatagramIterator& scan, BamReader* manager);
   void fillin(DatagramIterator& scan, BamReader* manager);
 
 
 public:
 public:

+ 14 - 1
panda/src/sgmanip/nodePath.I

@@ -1099,7 +1099,7 @@ has_color() const {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_bin() {
 clear_bin() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  arc()->clear_transition(TextureTransition::get_class_type());
+  arc()->clear_transition(GeomBinTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1130,6 +1130,19 @@ clear_texture() {
   arc()->clear_transition(TextureTransition::get_class_type());
   arc()->clear_transition(TextureTransition::get_class_type());
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::clear_material
+//       Access: Public
+//  Description: Completely removes any material adjustment that may
+//               have been set via set_material() from this particular
+//               arc.
+////////////////////////////////////////////////////////////////////
+INLINE void NodePath::
+clear_material() {
+  nassertv(has_arcs());
+  arc()->clear_transition(MaterialTransition::get_class_type());
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::clear_fog
 //     Function: NodePath::clear_fog
 //       Access: Public
 //       Access: Public

+ 73 - 0
panda/src/sgmanip/nodePath.cxx

@@ -25,6 +25,7 @@
 #include <traverserVisitor.h>
 #include <traverserVisitor.h>
 #include <dftraverser.h>
 #include <dftraverser.h>
 #include <bamFile.h>
 #include <bamFile.h>
+#include <materialPool.h>
 
 
 #include <list>
 #include <list>
 
 
@@ -2013,6 +2014,78 @@ get_texture() const {
   return NULL;
   return NULL;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_material
+//       Access: Public
+//  Description: Sets the geometry at this level and below to render
+//               using the indicated material.
+//
+//               This operation copies the given material pointer.  If
+//               the material structure is changed later, it must be
+//               reapplied via another call to set_material().
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_material(Material *mat, int priority) {
+  nassertv(has_arcs());
+  nassertv(mat != NULL);
+
+  // We create a temporary Material pointer, a copy of the one we are
+  // given, to allow the user to monkey with the material and set it
+  // again later, with the desired effect.  If we stored the user's
+  // pointer directly, it would be bad if the user later modified the
+  // values within the Material.
+  PT(Material) temp = new Material(*mat);
+  const Material *mp = MaterialPool::get_material(temp);
+
+  MaterialTransition *mat_trans = new MaterialTransition(mp);
+  arc()->set_transition(mat_trans, priority);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::has_material
+//       Access: Public
+//  Description: Returns true if a material has been applied to this
+//               particular arc via set_material(), false otherwise.
+////////////////////////////////////////////////////////////////////
+bool NodePath::
+has_material() const {
+  nassertr(has_arcs(), false);
+
+  const MaterialTransition *mt;
+  if (get_transition_into(mt, arc())) {
+    return mt->is_on();
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::get_material
+//       Access: Public
+//  Description: Returns the material that has been set on this
+//               particular arc, or NULL if no material has been set.
+//               This is not necessarily the material that will be
+//               applied to the geometry at or below this level, as
+//               another material at a higher or lower level may
+//               override.
+//
+//               This function returns a copy of the given material,
+//               to allow changes, if desired.  Once changes are made,
+//               they should be reapplied via set_material().
+////////////////////////////////////////////////////////////////////
+PT(Material) NodePath::
+get_material() const {
+  nassertr(has_arcs(), NULL);
+
+  const MaterialTransition *mt;
+  if (get_transition_into(mt, arc())) {
+    if (mt->is_on()) {
+      return new Material(*mt->get_material());
+    }
+  }
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_fog
 //     Function: NodePath::set_fog
 //       Access: Public
 //       Access: Public

+ 7 - 0
panda/src/sgmanip/nodePath.h

@@ -20,6 +20,8 @@
 #include <alphaTransformTransition.h>
 #include <alphaTransformTransition.h>
 #include <colorTransition.h>
 #include <colorTransition.h>
 #include <textureTransition.h>
 #include <textureTransition.h>
+#include <materialTransition.h>
+#include <material.h>
 #include <fogTransition.h>
 #include <fogTransition.h>
 #include <compose_matrix.h>
 #include <compose_matrix.h>
 #include <renderModeTransition.h>
 #include <renderModeTransition.h>
@@ -408,6 +410,11 @@ PUBLISHED:
   bool has_texture_off() const;
   bool has_texture_off() const;
   Texture *get_texture() const;
   Texture *get_texture() const;
   
   
+  void set_material(Material *tex, int priority = 0);
+  INLINE void clear_material();
+  bool has_material() const;
+  PT(Material) get_material() const;
+  
   void set_fog(Fog *fog, int priority = 0);
   void set_fog(Fog *fog, int priority = 0);
   void set_fog_off(int priority = 0);
   void set_fog_off(int priority = 0);
   INLINE void clear_fog();
   INLINE void clear_fog();