diff --git a/panda/src/tinydisplay/init.cxx b/panda/src/tinydisplay/init.cxx index 7ba1ebb8ae..680e689812 100644 --- a/panda/src/tinydisplay/init.cxx +++ b/panda/src/tinydisplay/init.cxx @@ -23,6 +23,8 @@ void glInit(GLContext *c, ZBuffer *zbuffer) c->local_light_model=0; c->lighting_enabled=0; c->light_model_two_side = 0; + c->normalize_enabled = 0; + c->normal_scale = 1.0f; /* default materials */ for(i=0;i<2;i++) { diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index b0a9f8993f..6a78ea574d 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -108,6 +108,7 @@ reset() { _texfilter_state = 0; _texture_replace = false; _filled_flat = false; + _auto_rescale_normal = false; // Now that the GSG has been initialized, make it available for // optimizations. @@ -1397,6 +1398,12 @@ set_state_and_transform(const RenderState *target, do_issue_cull_face(); _state._cull_face = _target._cull_face; } + + if (_target._rescale_normal != _state._rescale_normal) { + PStatTimer timer(_draw_set_state_rescale_normal_pcollector); + do_issue_rescale_normal(); + _state._rescale_normal = _target._rescale_normal; + } if (_target._render_mode != _state._render_mode) { PStatTimer timer(_draw_set_state_render_mode_pcollector); @@ -1784,6 +1791,10 @@ void TinyGraphicsStateGuardian:: do_issue_transform() { _transform_state_pcollector.add_level(1); _transform_stale = true; + + if (_auto_rescale_normal) { + do_auto_rescale_normal(); + } } //////////////////////////////////////////////////////////////////// @@ -1826,6 +1837,41 @@ do_issue_render_mode() { } } +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::do_issue_rescale_normal +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +do_issue_rescale_normal() { + const RescaleNormalAttrib *attrib = _target._rescale_normal; + RescaleNormalAttrib::Mode mode = attrib->get_mode(); + + _auto_rescale_normal = false; + + switch (mode) { + case RescaleNormalAttrib::M_none: + _c->normalize_enabled = false; + _c->normal_scale = 1.0f; + break; + + case RescaleNormalAttrib::M_normalize: + _c->normalize_enabled = true; + _c->normal_scale = 1.0f; + break; + + case RescaleNormalAttrib::M_rescale: + case RescaleNormalAttrib::M_auto: + _auto_rescale_normal = true; + do_auto_rescale_normal(); + break; + + default: + tinydisplay_cat.error() + << "Unknown rescale_normal mode " << (int)mode << endl; + } +} + //////////////////////////////////////////////////////////////////// // Function: TinyGraphicsStateGuardian::do_issue_cull_face // Access: Protected @@ -2583,6 +2629,26 @@ setup_material(GLMaterial *gl_material, const Material *material) { } } +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::do_auto_rescale_normal +// Access: Protected +// Description: Sets the state to either rescale or normalize the +// normals according to the current transform. +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +do_auto_rescale_normal() { + if (_internal_transform->has_uniform_scale()) { + // There's a uniform scale; rescale the normals uniformly. + _c->normalize_enabled = false; + _c->normal_scale = _internal_transform->get_uniform_scale(); + + } else { + // If there's a non-uniform scale, normalize everything. + _c->normalize_enabled = true; + _c->normal_scale = 1.0f; + } +} + //////////////////////////////////////////////////////////////////// // Function: TinyGraphicsStateGuardian::load_matrix // Access: Private, Static diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h index edb05814a5..1f4535b674 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h @@ -100,6 +100,7 @@ private: void do_issue_transform(); void do_issue_render_mode(); void do_issue_cull_face(); + void do_issue_rescale_normal(); void do_issue_material(); void do_issue_texture(); void do_issue_scissor(); @@ -120,6 +121,7 @@ private: static void copy_rgba_image(ZTextureLevel *dest, int xsize, int ysize, Texture *tex, int level); void setup_material(GLMaterial *gl_material, const Material *material); + void do_auto_rescale_normal(); static void load_matrix(M4 *matrix, const TransformState *transform); static int get_color_blend_op(ColorBlendAttrib::Operand operand); static ZB_lookupTextureFunc get_tex_filter_func(Texture::FilterType filter); @@ -144,6 +146,7 @@ private: int _texfilter_state; bool _texture_replace; bool _filled_flat; + bool _auto_rescale_normal; CPT(TransformState) _scissor_mat; diff --git a/panda/src/tinydisplay/vertex.cxx b/panda/src/tinydisplay/vertex.cxx index acaa3c218a..8c76f9810d 100644 --- a/panda/src/tinydisplay/vertex.cxx +++ b/panda/src/tinydisplay/vertex.cxx @@ -54,9 +54,9 @@ void gl_vertex_transform(GLContext * c, GLVertex * v) m = &c->matrix_model_view_inv.m[0][0]; n = &c->current_normal; - v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]); - v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]); - v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]); + v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]) * c->normal_scale; + v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]) * c->normal_scale; + v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]) * c->normal_scale; if (c->normalize_enabled) { gl_V3_Norm(&v->normal); diff --git a/panda/src/tinydisplay/zgl.h b/panda/src/tinydisplay/zgl.h index a09f460d1e..3be7e123dc 100644 --- a/panda/src/tinydisplay/zgl.h +++ b/panda/src/tinydisplay/zgl.h @@ -172,6 +172,8 @@ typedef struct GLContext { int cull_face_enabled; int cull_clockwise; int normalize_enabled; + float normal_scale; + gl_draw_triangle_func draw_triangle_front,draw_triangle_back; ZB_fillTriangleFunc zb_fill_tri;