From afe7b4b82947a99b9439b39bbee5ec0b9cbfcecc Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 30 Jul 2004 00:39:16 +0000 Subject: [PATCH] multitexture support --- .../eggcharbase/eggCharacterCollection.cxx | 32 +++-- .../src/eggcharbase/eggCharacterCollection.h | 2 + pandatool/src/palettizer/textureReference.cxx | 113 ++++++++++++------ pandatool/src/palettizer/textureReference.h | 3 +- 4 files changed, 104 insertions(+), 46 deletions(-) diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.cxx b/pandatool/src/eggcharbase/eggCharacterCollection.cxx index 03c3e028e5..2bbe9f4418 100644 --- a/pandatool/src/eggcharbase/eggCharacterCollection.cxx +++ b/pandatool/src/eggcharbase/eggCharacterCollection.cxx @@ -26,6 +26,7 @@ #include "eggTable.h" #include "eggPrimitive.h" #include "eggVertex.h" +#include "eggVertexUV.h" #include "eggMorphList.h" #include "eggSAnimData.h" #include "indirectCompareNames.h" @@ -347,6 +348,7 @@ scan_for_morphs(EggNode *egg_node, int model_index, EggVertex *vertex = (*vi); add_morph_back_pointers(vertex, vertex, model_index, char_data); + add_morph_back_pointers_vertex(vertex, vertex, model_index, char_data); EggMorphVertexList::const_iterator mvi; for (mvi = vertex->_dxyzs.begin(); @@ -424,14 +426,6 @@ add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); } - EggMorphTexCoordList::const_iterator mti; - for (mti = attrib->_duvs.begin(); - mti != attrib->_duvs.end(); - ++mti) { - const EggMorphTexCoord &morph = (*mti); - char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); - } - EggMorphColorList::const_iterator mci; for (mci = attrib->_drgbas.begin(); mci != attrib->_drgbas.end(); @@ -441,6 +435,28 @@ add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, } } +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::add_morph_back_pointers_vertex +// Access: Private +// Description: Adds the back pointers for the kinds of morphs we +// might find in an EggVertex object. +//////////////////////////////////////////////////////////////////// +void EggCharacterCollection:: +add_morph_back_pointers_vertex(EggVertex *vertex, EggObject *egg_object, + int model_index, EggCharacterData *char_data) { + EggVertex::const_uv_iterator ui; + for (ui = vertex->uv_begin(); ui != vertex->uv_end(); ++ui) { + EggVertexUV *vert_uv = (*ui); + EggMorphTexCoordList::const_iterator mti; + for (mti = vert_uv->_duvs.begin(); + mti != vert_uv->_duvs.end(); + ++mti) { + const EggMorphTexCoord &morph = (*mti); + char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: EggCharacterCollection::match_egg_nodes // Access: Private diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.h b/pandatool/src/eggcharbase/eggCharacterCollection.h index d33d99ffc8..7b8357215e 100644 --- a/pandatool/src/eggcharbase/eggCharacterCollection.h +++ b/pandatool/src/eggcharbase/eggCharacterCollection.h @@ -92,6 +92,8 @@ private: void add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, int model_index, EggCharacterData *char_data); + void add_morph_back_pointers_vertex(EggVertex *vertex, EggObject *egg_object, + int model_index, EggCharacterData *char_data); // The _top_egg_nodes member is only used temporarily, when adding // each pre-existing egg file to the structure for the first time. diff --git a/pandatool/src/palettizer/textureReference.cxx b/pandatool/src/palettizer/textureReference.cxx index c3b4764ebd..5528ab740c 100644 --- a/pandatool/src/palettizer/textureReference.cxx +++ b/pandatool/src/palettizer/textureReference.cxx @@ -131,8 +131,8 @@ from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex) { get_uv_range(_egg_data, pal->_remap_uv); - _wrap_u = egg_tex->determine_wrap_u(); - _wrap_v = egg_tex->determine_wrap_v(); + _wrap_u = _egg_tex->determine_wrap_u(); + _wrap_v = _egg_tex->determine_wrap_v(); } //////////////////////////////////////////////////////////////////// @@ -450,7 +450,9 @@ update_egg() { // Finally, go back and actually adjust the UV's to match what we // claimed they could be. - update_uv_range(_egg_data, pal->_remap_uv); + if (_egg_tex->get_tex_gen() == EggTexture::TG_unspecified) { + update_uv_range(_egg_data, pal->_remap_uv); + } } //////////////////////////////////////////////////////////////////// @@ -550,12 +552,15 @@ write(ostream &out, int indent_level) const { // the texture in a palette); they will actually be // applied when update_uv_range(), below, is called // later. +// +// The return value is true if the search should +// continue, or false if it should abort prematurely. //////////////////////////////////////////////////////////////////// -void TextureReference:: +bool TextureReference:: get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { if (group->is_of_type(EggGroup::get_class_type())) { EggGroup *egg_group; - DCAST_INTO_V(egg_group, group); + DCAST_INTO_R(egg_group, group, false); if (egg_group->get_dart_type() != EggGroup::DT_none) { // If it's a character, we might change the kind of remapping we @@ -572,11 +577,11 @@ get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { EggNode *child = (*ci); if (child->is_of_type(EggNurbsSurface::get_class_type())) { EggNurbsSurface *nurbs = DCAST(EggNurbsSurface, child); - if (nurbs->has_texture() && nurbs->get_texture() == _egg_tex) { + if (nurbs->has_texture(_egg_tex)) { // Here's a NURBS surface that references the texture. Unlike // other kinds of geometries, NURBS don't store UV's; they're // implicit in the surface. NURBS UV's will always run in the - // range (0,0) - (1,1). However, we do need to apply the + // range (0, 0) - (1, 1). However, we do need to apply the // texture matrix. // We also don't count the NURBS surfaces in with the group's @@ -585,42 +590,49 @@ get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { // up the group UV's is so we can consider adjusting them // later). Instead, we just accumulate the NURBS UV's // directly into our total. - - static const int num_nurbs_uvs = 4; - static TexCoordd nurbs_uvs[num_nurbs_uvs] = { - TexCoordd(0.0, 0.0), - TexCoordd(0.0, 1.0), - TexCoordd(1.0, 1.0), - TexCoordd(1.0, 0.0) - }; - - for (int i = 0; i < num_nurbs_uvs; i++) { - TexCoordd uv = nurbs_uvs[i] * _tex_mat; - collect_uv(_any_uvs, _min_uv, _max_uv, uv, uv); - } + collect_nominal_uv_range(); } } else if (child->is_of_type(EggPrimitive::get_class_type())) { EggPrimitive *geom = DCAST(EggPrimitive, child); - if (geom->has_texture() && geom->get_texture() == _egg_tex) { + if (geom->has_texture(_egg_tex)) { // Here's a piece of geometry that references this texture. // Walk through its vertices and get its UV's. - TexCoordd geom_min_uv, geom_max_uv; - if (get_geom_uvs(geom, geom_min_uv, geom_max_uv)) { - if (remap == Palettizer::RU_poly) { - LVector2d trans = translate_uv(geom_min_uv, geom_max_uv); - geom_min_uv += trans; - geom_max_uv += trans; + if (_egg_tex->get_tex_gen() != EggTexture::TG_unspecified) { + // If the texture has a TexGen mode, we don't check the UV + // range on the model, since that doesn't matter. Instead, + // we assume the texture is used in the range (0, 0) - (1, + // 1), which will be true for a sphere map, although the + // effective range is a little less clear for the + // TG_world_position and similar modes. + collect_nominal_uv_range(); + + // In fact, now we can return, having found at least one + // model that references the texture; there's no need to + // search further. + return false; + + } else { + TexCoordd geom_min_uv, geom_max_uv; + + if (get_geom_uvs(geom, geom_min_uv, geom_max_uv)) { + if (remap == Palettizer::RU_poly) { + LVector2d trans = translate_uv(geom_min_uv, geom_max_uv); + geom_min_uv += trans; + geom_max_uv += trans; + } + collect_uv(group_any_uvs, group_min_uv, group_max_uv, + geom_min_uv, geom_max_uv); } - collect_uv(group_any_uvs, group_min_uv, group_max_uv, - geom_min_uv, geom_max_uv); } } - + } else if (child->is_of_type(EggGroupNode::get_class_type())) { EggGroupNode *cg = DCAST(EggGroupNode, child); - get_uv_range(cg, remap); + if (!get_uv_range(cg, remap)) { + return false; + } } } @@ -632,6 +644,8 @@ get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { } collect_uv(_any_uvs, _min_uv, _max_uv, group_min_uv, group_max_uv); } + + return true; } //////////////////////////////////////////////////////////////////// @@ -666,7 +680,7 @@ update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { } else if (child->is_of_type(EggPrimitive::get_class_type())) { if (remap != Palettizer::RU_never) { EggPrimitive *geom = DCAST(EggPrimitive, child); - if (geom->has_texture() && geom->get_texture() == _egg_tex) { + if (geom->has_texture(_egg_tex)) { TexCoordd geom_min_uv, geom_max_uv; if (get_geom_uvs(geom, geom_min_uv, geom_max_uv)) { @@ -698,7 +712,7 @@ update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { EggNode *child = (*ci); if (child->is_of_type(EggPrimitive::get_class_type())) { EggPrimitive *geom = DCAST(EggPrimitive, child); - if (geom->has_texture() && geom->get_texture() == _egg_tex) { + if (geom->has_texture(_egg_tex)) { translate_geom_uvs(geom, trans); } } @@ -717,13 +731,14 @@ update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { bool TextureReference:: get_geom_uvs(EggPrimitive *geom, TexCoordd &geom_min_uv, TexCoordd &geom_max_uv) { + string uv_name = _egg_tex->get_uv_name(); bool geom_any_uvs = false; EggPrimitive::iterator pi; for (pi = geom->begin(); pi != geom->end(); ++pi) { EggVertex *vtx = (*pi); - if (vtx->has_uv()) { - TexCoordd uv = vtx->get_uv() * _tex_mat; + if (vtx->has_uv(uv_name)) { + TexCoordd uv = vtx->get_uv(uv_name) * _tex_mat; collect_uv(geom_any_uvs, geom_min_uv, geom_max_uv, uv, uv); } } @@ -739,12 +754,14 @@ get_geom_uvs(EggPrimitive *geom, //////////////////////////////////////////////////////////////////// void TextureReference:: translate_geom_uvs(EggPrimitive *geom, const TexCoordd &trans) const { + string uv_name = _egg_tex->get_uv_name(); + EggPrimitive::iterator pi; for (pi = geom->begin(); pi != geom->end(); ++pi) { EggVertex *vtx = (*pi); - if (vtx->has_uv()) { + if (vtx->has_uv(uv_name)) { EggVertex vtx_copy(*vtx); - vtx_copy.set_uv(vtx_copy.get_uv() + trans); + vtx_copy.set_uv(uv_name, vtx_copy.get_uv(uv_name) + trans); EggVertex *new_vtx = vtx->get_pool()->create_unique_vertex(vtx_copy); if (new_vtx->gref_size() != vtx->gref_size()) { @@ -756,6 +773,28 @@ translate_geom_uvs(EggPrimitive *geom, const TexCoordd &trans) const { } } +//////////////////////////////////////////////////////////////////// +// Function: TextureReference::collect_nominal_uv_range +// Access: Private +// Description: Updates _any_uvs, _min_uv, and _max_uv with the range +// (0, 0) - (1, 1), adjusted by the texture matrix. +//////////////////////////////////////////////////////////////////// +void TextureReference:: +collect_nominal_uv_range() { + static const int num_nurbs_uvs = 4; + static TexCoordd nurbs_uvs[num_nurbs_uvs] = { + TexCoordd(0.0, 0.0), + TexCoordd(0.0, 1.0), + TexCoordd(1.0, 1.0), + TexCoordd(1.0, 0.0) + }; + + for (int i = 0; i < num_nurbs_uvs; i++) { + TexCoordd uv = nurbs_uvs[i] * _tex_mat; + collect_uv(_any_uvs, _min_uv, _max_uv, uv, uv); + } +} + //////////////////////////////////////////////////////////////////// // Function: TextureReference::collect_uv // Access: Private, Static diff --git a/pandatool/src/palettizer/textureReference.h b/pandatool/src/palettizer/textureReference.h index ec5c9a234e..15a2a5fa04 100644 --- a/pandatool/src/palettizer/textureReference.h +++ b/pandatool/src/palettizer/textureReference.h @@ -80,12 +80,13 @@ public: void write(ostream &out, int indent_level = 0) const; private: - void get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap); + bool get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap); void update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap); bool get_geom_uvs(EggPrimitive *geom, TexCoordd &geom_min_uv, TexCoordd &geom_max_uv); void translate_geom_uvs(EggPrimitive *geom, const TexCoordd &trans) const; + void collect_nominal_uv_range(); static void collect_uv(bool &any_uvs, TexCoordd &min_uv, TexCoordd &max_uv, const TexCoordd &got_min_uv, const TexCoordd &got_max_uv);