Browse Source

add RescaleNormalAttrib

David Rose 21 years ago
parent
commit
f8ddceb035

+ 7 - 0
direct/src/showbase/ShowBase.py

@@ -568,6 +568,13 @@ class ShowBase(DirectObject.DirectObject):
         rendering 3-d geometry.
         """
         self.render = NodePath('render')
+
+        # Temporary try..except for old pandas.
+        try:
+            self.render.node().setAttrib(RescaleNormalAttrib.makeDefault());
+        except:
+            pass
+        
         self.render.setTwoSided(0)
         self.backfaceCullingEnabled = 1
         self.textureEnabled = 1

+ 3 - 0
panda/src/framework/windowFramework.cxx

@@ -40,6 +40,7 @@
 #include "depthTestAttrib.h"
 #include "depthWriteAttrib.h"
 #include "cullFaceAttrib.h"
+#include "rescaleNormalAttrib.h"
 #include "pgTop.h"
 #include "geomNode.h"
 #include "geomTristrip.h"
@@ -228,6 +229,8 @@ get_render() {
   if (_render.is_empty()) {
     _render = NodePath("render");
 
+    _render.node()->set_attrib(RescaleNormalAttrib::make_default());
+
     // This is maybe here temporarily, and maybe not.
     _render.set_two_sided(0);
   }

+ 98 - 7
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -41,6 +41,7 @@
 #include "cgShaderAttrib.h"
 #include "materialAttrib.h"
 #include "renderModeAttrib.h"
+#include "rescaleNormalAttrib.h"
 #include "fogAttrib.h"
 #include "depthOffsetAttrib.h"
 #include "fog.h"
@@ -309,8 +310,13 @@ reset() {
   get_extra_extensions();
   report_extensions();
 
-  _supports_bgr = has_extension("GL_EXT_bgra");
-  _supports_multisample = has_extension("GL_ARB_multisample");
+  _supports_bgr = 
+    has_extension("GL_EXT_bgra") || is_at_least_version(1, 2);
+  _supports_rescale_normal = 
+    has_extension("GL_EXT_rescale_normal") || is_at_least_version(1, 2);
+
+  _supports_multisample = 
+    has_extension("GL_ARB_multisample");
 
   _supports_generate_mipmap = 
     has_extension("GL_SGIS_generate_mipmap") || is_at_least_version(1, 4);
@@ -414,6 +420,8 @@ reset() {
 
   report_my_gl_errors();
 
+  _auto_rescale_normal = false;
+
   // All GL implementations have the following buffers.
   _buffer_mask = (RenderBuffer::T_color |
                   RenderBuffer::T_depth |
@@ -475,11 +483,6 @@ reset() {
   _cg_shader = (CgShader *)NULL;
 #endif
 
-  // Should we normalize lighting normals?
-  if (CLP(auto_normalize_lighting)) {
-    GLP(Enable)(GL_NORMALIZE);
-  }
-
   // Count the max number of lights
   GLint max_lights;
   GLP(GetIntegerv)(GL_MAX_LIGHTS, &max_lights);
@@ -2288,6 +2291,11 @@ issue_transform(const TransformState *transform) {
   GLP(MatrixMode)(GL_MODELVIEW);
   GLP(LoadMatrixf)(transform->get_mat().get_data());
 
+  _transform = transform;
+  if (_auto_rescale_normal) {
+    do_auto_rescale_normal();
+  }
+
   report_my_gl_errors();
 }
 
@@ -2533,6 +2541,53 @@ issue_render_mode(const RenderModeAttrib *attrib) {
   report_my_gl_errors();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(GraphicsStateGuardian)::issue_rescale_normal
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+issue_rescale_normal(const RescaleNormalAttrib *attrib) {
+  RescaleNormalAttrib::Mode mode = attrib->get_mode();
+
+  _auto_rescale_normal = false;
+
+  switch (mode) {
+  case RescaleNormalAttrib::M_none:
+    GLP(Disable)(GL_NORMALIZE);
+    if (_supports_rescale_normal) {
+      GLP(Disable)(GL_RESCALE_NORMAL);
+    }
+    break;
+
+  case RescaleNormalAttrib::M_rescale:
+    if (_supports_rescale_normal) {
+      GLP(Enable)(GL_RESCALE_NORMAL);
+      GLP(Disable)(GL_NORMALIZE);
+    } else {
+      GLP(Enable)(GL_NORMALIZE);
+    }
+    break;
+
+  case RescaleNormalAttrib::M_normalize:
+    GLP(Enable)(GL_NORMALIZE);
+    if (_supports_rescale_normal) {
+      GLP(Disable)(GL_RESCALE_NORMAL);
+    }
+    break;
+
+  case RescaleNormalAttrib::M_auto:
+    _auto_rescale_normal = true;
+    do_auto_rescale_normal();
+    break;
+
+  default:
+    GLCAT.error()
+      << "Unknown rescale_normal mode " << (int)mode << endl;
+  }
+  report_my_gl_errors();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(GraphicsStateGuardian)::issue_texture_apply
 //       Access: Public, Virtual
@@ -4621,6 +4676,42 @@ get_untextured_state() {
   return state;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(GraphicsStateGuardian)::do_auto_rescale_normal
+//       Access: Protected
+//  Description: Issues the appropriate GL commands to either rescale
+//               or normalize the normals according to the current
+//               transform.
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+do_auto_rescale_normal() {
+  if (_transform->has_uniform_scale()) {
+    if (IS_NEARLY_EQUAL(_transform->get_uniform_scale(), 1.0f)) {
+      // If there's no scale at all, don't do anything.
+      GLP(Disable)(GL_NORMALIZE);
+      if (_supports_rescale_normal) {
+        GLP(Disable)(GL_RESCALE_NORMAL);
+      }
+      
+    } else {
+      // There's a uniform scale; use the rescale feature if available.
+      if (_supports_rescale_normal) {
+        GLP(Enable)(GL_RESCALE_NORMAL);
+        GLP(Disable)(GL_NORMALIZE);
+      } else {
+        GLP(Enable)(GL_NORMALIZE);
+      }
+    }
+
+  } else {
+    // If there's a non-uniform scale, normalize everything.
+    GLP(Enable)(GL_NORMALIZE);
+    if (_supports_rescale_normal) {
+      GLP(Disable)(GL_RESCALE_NORMAL);
+    }
+  }
+}
+
 #ifndef NDEBUG
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(GraphicsStateGuardian)::build_phony_mipmaps

+ 5 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -110,6 +110,7 @@ public:
   virtual void issue_texture(const TextureAttrib *attrib);
   virtual void issue_material(const MaterialAttrib *attrib);
   virtual void issue_render_mode(const RenderModeAttrib *attrib);
+  virtual void issue_rescale_normal(const RescaleNormalAttrib *attrib);
   virtual void issue_texture_apply(const TextureApplyAttrib *attrib);
   virtual void issue_color_write(const ColorWriteAttrib *attrib);
   virtual void issue_depth_test(const DepthTestAttrib *attrib);
@@ -228,6 +229,8 @@ protected:
 
   static CPT(RenderState) get_untextured_state();
 
+  void do_auto_rescale_normal();
+
 #ifndef NDEBUG
   void build_phony_mipmaps(Texture *tex);
   void build_phony_mipmap_level(int level, int xsize, int ysize);
@@ -271,6 +274,7 @@ protected:
 #endif
 
   int _pass_number;
+  bool _auto_rescale_normal;
   
   int _error_count;
 
@@ -279,6 +283,7 @@ protected:
 
 public:
   bool _supports_bgr;
+  bool _supports_rescale_normal;
 
   bool _supports_multitexture;
   PFNGLACTIVETEXTUREPROC _glActiveTexture;

+ 2 - 0
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -60,6 +60,7 @@ class TextureAttrib;
 class LightAttrib;
 class MaterialAttrib;
 class RenderModeAttrib;
+class RescaleNormalAttrib;
 class ColorBlendAttrib;
 class TextureApplyAttrib;
 class ColorWriteAttrib;
@@ -186,6 +187,7 @@ public:
   virtual void issue_light(const LightAttrib *) { }
   virtual void issue_material(const MaterialAttrib *) { }
   virtual void issue_render_mode(const RenderModeAttrib *) { }
+  virtual void issue_rescale_normal(const RescaleNormalAttrib *) { }
   virtual void issue_texture_apply(const TextureApplyAttrib *) { }
   virtual void issue_color_write(const ColorWriteAttrib *) { }
   virtual void issue_depth_test(const DepthTestAttrib *) { }

+ 3 - 0
panda/src/pgraph/Sources.pp

@@ -80,6 +80,7 @@
     renderEffects.I renderEffects.h \
     renderModeAttrib.I renderModeAttrib.h \
     renderState.I renderState.h \
+    rescaleNormalAttrib.I rescaleNormalAttrib.h \
     sceneGraphAnalyzer.h \
     sceneGraphReducer.I sceneGraphReducer.h \
     sceneSetup.I sceneSetup.h \
@@ -172,6 +173,7 @@
     renderEffects.cxx \
     renderModeAttrib.cxx \
     renderState.cxx \
+    rescaleNormalAttrib.cxx \
     sceneGraphAnalyzer.cxx \
     sceneGraphReducer.cxx \
     sceneSetup.cxx \
@@ -262,6 +264,7 @@
     renderEffects.I renderEffects.h \
     renderModeAttrib.I renderModeAttrib.h \
     renderState.I renderState.h \
+    rescaleNormalAttrib.I rescaleNormalAttrib.h \
     sceneGraphAnalyzer.h \
     sceneGraphReducer.I sceneGraphReducer.h \
     sceneSetup.I sceneSetup.h \

+ 2 - 0
panda/src/pgraph/config_pgraph.cxx

@@ -74,6 +74,7 @@
 #include "renderEffects.h"
 #include "renderModeAttrib.h"
 #include "renderState.h"
+#include "rescaleNormalAttrib.h"
 #include "selectiveChildNode.h"
 #include "sequenceNode.h"
 #include "showBoundsEffect.h"
@@ -264,6 +265,7 @@ init_libpgraph() {
   RenderEffects::init_type();
   RenderModeAttrib::init_type();
   RenderState::init_type();
+  RescaleNormalAttrib::init_type();
   SelectiveChildNode::init_type();
   SequenceNode::init_type();
   ShowBoundsEffect::init_type();

+ 1 - 0
panda/src/pgraph/pgraph_composite2.cxx

@@ -27,6 +27,7 @@
 #include "renderEffects.cxx"
 #include "renderModeAttrib.cxx"
 #include "renderState.cxx"
+#include "rescaleNormalAttrib.cxx"
 #include "sceneGraphAnalyzer.cxx"
 #include "sceneGraphReducer.cxx"
 #include "selectiveChildNode.cxx"

+ 40 - 0
panda/src/pgraph/rescaleNormalAttrib.I

@@ -0,0 +1,40 @@
+// Filename: rescaleNormalAttrib.I
+// Created by:  drose (30Dec04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::Constructor
+//       Access: Private
+//  Description: Use RescaleNormalAttrib::make() to construct a new
+//               RescaleNormalAttrib object.
+////////////////////////////////////////////////////////////////////
+INLINE RescaleNormalAttrib::
+RescaleNormalAttrib(RescaleNormalAttrib::Mode mode) :
+  _mode(mode)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::get_mode
+//       Access: Published
+//  Description: Returns the render mode.
+////////////////////////////////////////////////////////////////////
+INLINE RescaleNormalAttrib::Mode RescaleNormalAttrib::
+get_mode() const {
+  return _mode;
+}

+ 241 - 0
panda/src/pgraph/rescaleNormalAttrib.cxx

@@ -0,0 +1,241 @@
+// Filename: rescaleNormalAttrib.cxx
+// Created by:  drose (30Dec04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "rescaleNormalAttrib.h"
+#include "graphicsStateGuardianBase.h"
+#include "string_utils.h"
+#include "dcast.h"
+#include "bamReader.h"
+#include "bamWriter.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+#include "configVariableEnum.h"
+
+TypeHandle RescaleNormalAttrib::_type_handle;
+
+// This variable is defined here instead of in config_pgraph.cxx,
+// because it depends on rescaleNormalAttrib.h having already been
+// included.
+static ConfigVariableEnum<RescaleNormalAttrib::Mode> rescale_normals
+("rescale-normals", RescaleNormalAttrib::M_auto,
+ PRC_DESC("Specifies the kind of RescaleNormalAttrib that should be "
+          "created for the top of the scene graph.  This can automatically "
+          "ensure that your lighting normals are unit-length, which may be "
+          "particularly necessary in the presence of scales in the scene "
+          "graph.  Turning it off ('none') may produce a small performance "
+          "benefit."));
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::make
+//       Access: Published, Static
+//  Description: Constructs a new RescaleNormalAttrib object that
+//               specifies whether to rescale normals to compensate
+//               for transform scales or incorrectly defined normals.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) RescaleNormalAttrib::
+make(RescaleNormalAttrib::Mode mode) {
+  RescaleNormalAttrib *attrib = new RescaleNormalAttrib(mode);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::make_default
+//       Access: Published, Static
+//  Description: Constructs a RescaleNoramlAttrib object that's
+//               suitable for putting at the top of a scene graph.
+//               This will contain whatever attrib was suggested by
+//               the user's rescale-normals Config variable.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) RescaleNormalAttrib::
+make_default() {
+  RescaleNormalAttrib *attrib = new RescaleNormalAttrib(rescale_normals);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::issue
+//       Access: Public, Virtual
+//  Description: Calls the appropriate method on the indicated GSG
+//               to issue the graphics commands appropriate to the
+//               given attribute.  This is normally called
+//               (indirectly) only from
+//               GraphicsStateGuardian::set_state() or modify_state().
+////////////////////////////////////////////////////////////////////
+void RescaleNormalAttrib::
+issue(GraphicsStateGuardianBase *gsg) const {
+  gsg->issue_rescale_normal(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void RescaleNormalAttrib::
+output(ostream &out) const {
+  out << get_type() << ":" << get_mode();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::compare_to_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived RescaleNormalAttrib
+//               types to return a unique number indicating whether
+//               this RescaleNormalAttrib is equivalent to the other one.
+//
+//               This should return 0 if the two RescaleNormalAttrib objects
+//               are equivalent, a number less than zero if this one
+//               should be sorted before the other one, and a number
+//               greater than zero otherwise.
+//
+//               This will only be called with two RescaleNormalAttrib
+//               objects whose get_type() functions return the same.
+////////////////////////////////////////////////////////////////////
+int RescaleNormalAttrib::
+compare_to_impl(const RenderAttrib *other) const {
+  const RescaleNormalAttrib *ta;
+  DCAST_INTO_R(ta, other, 0);
+  return (int)_mode - (int)ta->_mode;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::make_default_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived RescaleNormalAttrib
+//               types to specify what the default property for a
+//               RescaleNormalAttrib of this type should be.
+//
+//               This should return a newly-allocated RescaleNormalAttrib of
+//               the same type that corresponds to whatever the
+//               standard default for this kind of RescaleNormalAttrib is.
+////////////////////////////////////////////////////////////////////
+RenderAttrib *RescaleNormalAttrib::
+make_default_impl() const {
+  return new RescaleNormalAttrib(M_none);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               RescaleNormalAttrib.
+////////////////////////////////////////////////////////////////////
+void RescaleNormalAttrib::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void RescaleNormalAttrib::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  RenderAttrib::write_datagram(manager, dg);
+
+  dg.add_int8(_mode);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type RescaleNormalAttrib is encountered
+//               in the Bam file.  It should create the RescaleNormalAttrib
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *RescaleNormalAttrib::
+make_from_bam(const FactoryParams &params) {
+  RescaleNormalAttrib *attrib = new RescaleNormalAttrib(M_none);
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  attrib->fillin(scan, manager);
+
+  return attrib;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new RescaleNormalAttrib.
+////////////////////////////////////////////////////////////////////
+void RescaleNormalAttrib::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  RenderAttrib::fillin(scan, manager);
+
+  _mode = (Mode)scan.get_int8();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::Mode output operator
+//  Description:
+////////////////////////////////////////////////////////////////////
+ostream &
+operator << (ostream &out, RescaleNormalAttrib::Mode mode) {
+  switch (mode) {
+  case RescaleNormalAttrib::M_none:
+    return out << "none";
+
+  case RescaleNormalAttrib::M_rescale:
+    return out << "rescale";
+
+  case RescaleNormalAttrib::M_normalize:
+    return out << "normalize";
+
+  case RescaleNormalAttrib::M_auto:
+    return out << "auto";
+  }
+
+  return out << "(**invalid RescaleNormalAttrib::Mode(" << (int)mode << ")**)";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RescaleNormalAttrib::Mode input operator
+//  Description:
+////////////////////////////////////////////////////////////////////
+istream &
+operator >> (istream &in, RescaleNormalAttrib::Mode &mode) {
+  string word;
+  in >> word;
+
+  if (cmp_nocase(word, "none") == 0) {
+    mode = RescaleNormalAttrib::M_none;
+
+  } else if (cmp_nocase(word, "rescale") == 0) {
+    mode = RescaleNormalAttrib::M_rescale;
+
+  } else if (cmp_nocase(word, "normalize") == 0) {
+    mode = RescaleNormalAttrib::M_normalize;
+
+  } else if (cmp_nocase(word, "auto") == 0) {
+    mode = RescaleNormalAttrib::M_auto;
+
+  } else {
+    pgraph_cat.error()
+      << "Invalid RescaleNormalAttrib::Mode value: " << word << "\n";
+    mode = RescaleNormalAttrib::M_none;
+  }
+
+  return in;
+}

+ 103 - 0
panda/src/pgraph/rescaleNormalAttrib.h

@@ -0,0 +1,103 @@
+// Filename: rescaleNormalAttrib.h
+// Created by:  drose (30Dec04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef RESCALENORMALATTRIB_H
+#define RESCALENORMALATTRIB_H
+
+#include "pandabase.h"
+
+#include "renderAttrib.h"
+
+class FactoryParams;
+
+////////////////////////////////////////////////////////////////////
+//       Class : RescaleNormalAttrib
+// Description : Specifies how polygons are to be drawn.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA RescaleNormalAttrib : public RenderAttrib {
+PUBLISHED:
+  enum Mode {
+    // No adjustments are made to normals.
+    M_none,
+
+    // Normals are counterscaled by the transform's uniform scale, if
+    // supported by the graphics API.
+    M_rescale,
+
+    // Normals are scaled to unit length; potentially expensive.
+    M_normalize,
+
+    // Normals are counterscaled in the presence of a uniform scale
+    // transform, or normalized in the presence of a non-uniform scale
+    // transform.
+    M_auto,
+  };
+
+private:
+  INLINE RescaleNormalAttrib(Mode mode);
+
+PUBLISHED:
+  static CPT(RenderAttrib) make(Mode mode);
+  static CPT(RenderAttrib) make_default();
+
+  INLINE Mode get_mode() const;
+
+public:
+  virtual void issue(GraphicsStateGuardianBase *gsg) const;
+  virtual void output(ostream &out) const;
+
+protected:
+  virtual int compare_to_impl(const RenderAttrib *other) const;
+  virtual RenderAttrib *make_default_impl() const;
+
+private:
+  Mode _mode;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    RenderAttrib::init_type();
+    register_type(_type_handle, "RescaleNormalAttrib",
+                  RenderAttrib::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+EXPCL_PANDA ostream &operator << (ostream &out, RescaleNormalAttrib::Mode mode);
+EXPCL_PANDA istream &operator >> (istream &in, RescaleNormalAttrib::Mode &mode);
+
+#include "rescaleNormalAttrib.I"
+
+#endif
+