multitexture support

This commit is contained in:
David Rose 2004-07-30 00:39:16 +00:00
parent c7c639797e
commit afe7b4b829
4 changed files with 104 additions and 46 deletions

View File

@ -26,6 +26,7 @@
#include "eggTable.h" #include "eggTable.h"
#include "eggPrimitive.h" #include "eggPrimitive.h"
#include "eggVertex.h" #include "eggVertex.h"
#include "eggVertexUV.h"
#include "eggMorphList.h" #include "eggMorphList.h"
#include "eggSAnimData.h" #include "eggSAnimData.h"
#include "indirectCompareNames.h" #include "indirectCompareNames.h"
@ -347,6 +348,7 @@ scan_for_morphs(EggNode *egg_node, int model_index,
EggVertex *vertex = (*vi); EggVertex *vertex = (*vi);
add_morph_back_pointers(vertex, vertex, model_index, char_data); 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; EggMorphVertexList::const_iterator mvi;
for (mvi = vertex->_dxyzs.begin(); 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); 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; EggMorphColorList::const_iterator mci;
for (mci = attrib->_drgbas.begin(); for (mci = attrib->_drgbas.begin();
mci != attrib->_drgbas.end(); 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 // Function: EggCharacterCollection::match_egg_nodes
// Access: Private // Access: Private

View File

@ -92,6 +92,8 @@ private:
void add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, void add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object,
int model_index, EggCharacterData *char_data); 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 // The _top_egg_nodes member is only used temporarily, when adding
// each pre-existing egg file to the structure for the first time. // each pre-existing egg file to the structure for the first time.

View File

@ -131,8 +131,8 @@ from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex) {
get_uv_range(_egg_data, pal->_remap_uv); get_uv_range(_egg_data, pal->_remap_uv);
_wrap_u = egg_tex->determine_wrap_u(); _wrap_u = _egg_tex->determine_wrap_u();
_wrap_v = egg_tex->determine_wrap_v(); _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 // Finally, go back and actually adjust the UV's to match what we
// claimed they could be. // 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 // the texture in a palette); they will actually be
// applied when update_uv_range(), below, is called // applied when update_uv_range(), below, is called
// later. // 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) { get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) {
if (group->is_of_type(EggGroup::get_class_type())) { if (group->is_of_type(EggGroup::get_class_type())) {
EggGroup *egg_group; 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 (egg_group->get_dart_type() != EggGroup::DT_none) {
// If it's a character, we might change the kind of remapping we // 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); EggNode *child = (*ci);
if (child->is_of_type(EggNurbsSurface::get_class_type())) { if (child->is_of_type(EggNurbsSurface::get_class_type())) {
EggNurbsSurface *nurbs = DCAST(EggNurbsSurface, child); 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 // Here's a NURBS surface that references the texture. Unlike
// other kinds of geometries, NURBS don't store UV's; they're // other kinds of geometries, NURBS don't store UV's; they're
// implicit in the surface. NURBS UV's will always run in the // 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. // texture matrix.
// We also don't count the NURBS surfaces in with the group's // 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 // up the group UV's is so we can consider adjusting them
// later). Instead, we just accumulate the NURBS UV's // later). Instead, we just accumulate the NURBS UV's
// directly into our total. // directly into our total.
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);
}
} }
} else if (child->is_of_type(EggPrimitive::get_class_type())) { } else if (child->is_of_type(EggPrimitive::get_class_type())) {
EggPrimitive *geom = DCAST(EggPrimitive, child); 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. // Here's a piece of geometry that references this texture.
// Walk through its vertices and get its UV's. // 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 (_egg_tex->get_tex_gen() != EggTexture::TG_unspecified) {
if (remap == Palettizer::RU_poly) { // If the texture has a TexGen mode, we don't check the UV
LVector2d trans = translate_uv(geom_min_uv, geom_max_uv); // range on the model, since that doesn't matter. Instead,
geom_min_uv += trans; // we assume the texture is used in the range (0, 0) - (1,
geom_max_uv += trans; // 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())) { } else if (child->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *cg = DCAST(EggGroupNode, child); 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); 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())) { } else if (child->is_of_type(EggPrimitive::get_class_type())) {
if (remap != Palettizer::RU_never) { if (remap != Palettizer::RU_never) {
EggPrimitive *geom = DCAST(EggPrimitive, child); 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; TexCoordd geom_min_uv, geom_max_uv;
if (get_geom_uvs(geom, 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); EggNode *child = (*ci);
if (child->is_of_type(EggPrimitive::get_class_type())) { if (child->is_of_type(EggPrimitive::get_class_type())) {
EggPrimitive *geom = DCAST(EggPrimitive, child); 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); translate_geom_uvs(geom, trans);
} }
} }
@ -717,13 +731,14 @@ update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) {
bool TextureReference:: bool TextureReference::
get_geom_uvs(EggPrimitive *geom, get_geom_uvs(EggPrimitive *geom,
TexCoordd &geom_min_uv, TexCoordd &geom_max_uv) { TexCoordd &geom_min_uv, TexCoordd &geom_max_uv) {
string uv_name = _egg_tex->get_uv_name();
bool geom_any_uvs = false; bool geom_any_uvs = false;
EggPrimitive::iterator pi; EggPrimitive::iterator pi;
for (pi = geom->begin(); pi != geom->end(); ++pi) { for (pi = geom->begin(); pi != geom->end(); ++pi) {
EggVertex *vtx = (*pi); EggVertex *vtx = (*pi);
if (vtx->has_uv()) { if (vtx->has_uv(uv_name)) {
TexCoordd uv = vtx->get_uv() * _tex_mat; TexCoordd uv = vtx->get_uv(uv_name) * _tex_mat;
collect_uv(geom_any_uvs, geom_min_uv, geom_max_uv, uv, uv); collect_uv(geom_any_uvs, geom_min_uv, geom_max_uv, uv, uv);
} }
} }
@ -739,12 +754,14 @@ get_geom_uvs(EggPrimitive *geom,
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void TextureReference:: void TextureReference::
translate_geom_uvs(EggPrimitive *geom, const TexCoordd &trans) const { translate_geom_uvs(EggPrimitive *geom, const TexCoordd &trans) const {
string uv_name = _egg_tex->get_uv_name();
EggPrimitive::iterator pi; EggPrimitive::iterator pi;
for (pi = geom->begin(); pi != geom->end(); ++pi) { for (pi = geom->begin(); pi != geom->end(); ++pi) {
EggVertex *vtx = (*pi); EggVertex *vtx = (*pi);
if (vtx->has_uv()) { if (vtx->has_uv(uv_name)) {
EggVertex vtx_copy(*vtx); 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); EggVertex *new_vtx = vtx->get_pool()->create_unique_vertex(vtx_copy);
if (new_vtx->gref_size() != vtx->gref_size()) { 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 // Function: TextureReference::collect_uv
// Access: Private, Static // Access: Private, Static

View File

@ -80,12 +80,13 @@ public:
void write(ostream &out, int indent_level = 0) const; void write(ostream &out, int indent_level = 0) const;
private: 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); void update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap);
bool get_geom_uvs(EggPrimitive *geom, bool get_geom_uvs(EggPrimitive *geom,
TexCoordd &geom_min_uv, TexCoordd &geom_max_uv); TexCoordd &geom_min_uv, TexCoordd &geom_max_uv);
void translate_geom_uvs(EggPrimitive *geom, const TexCoordd &trans) const; 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, static void collect_uv(bool &any_uvs, TexCoordd &min_uv, TexCoordd &max_uv,
const TexCoordd &got_min_uv, const TexCoordd &got_min_uv,
const TexCoordd &got_max_uv); const TexCoordd &got_max_uv);