From 07d83f7a9c46659efecadee523916df4ac7c3012 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 12 Mar 2009 07:42:03 +0000 Subject: [PATCH] Overhauled UV-handling in order to have better support for multiple UV sets, I hope --- pandatool/src/daeegg/daeMaterials.cxx | 67 +++++++++++++++++----- pandatool/src/daeegg/daeMaterials.h | 11 +++- pandatool/src/daeegg/daeToEggConverter.cxx | 46 ++++++++------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/pandatool/src/daeegg/daeMaterials.cxx b/pandatool/src/daeegg/daeMaterials.cxx index ac32c9cd61..eead3fd31d 100755 --- a/pandatool/src/daeegg/daeMaterials.cxx +++ b/pandatool/src/daeegg/daeMaterials.cxx @@ -63,11 +63,15 @@ void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) { for (size_t vib = 0; vib < instance->GetVertexInputBindingCount(); ++vib) { const FCDMaterialInstanceBindVertexInput* mivib = instance->GetVertexInputBinding(vib); assert(mivib != NULL); + PT(DaeVertexInputBinding) bvi = new DaeVertexInputBinding(); + bvi->_input_semantic = mivib->inputSemantic; + bvi->_input_set = mivib->inputSet; #if FCOLLADA_VERSION >= 0x00030005 - _materials[semantic]->_uvsets[mivib->inputSet] = *mivib->semantic; + bvi->_semantic = *mivib->semantic; #else - _materials[semantic]->_uvsets[mivib->inputSet] = FROM_FSTRING(mivib->semantic); + bvi->_semantic = FROM_FSTRING(mivib->semantic); #endif + _materials[semantic]->_uvsets.push_back(bvi); } // Handle the material stuff @@ -81,13 +85,13 @@ void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) { // Grab the common profile effect const FCDEffectStandard* effect_common = (FCDEffectStandard *)effect->FindProfile(FUDaeProfileType::COMMON); if (effect_common == NULL) { - daeegg_cat.debug() << "Ignoring effect referenced by material with semantic " << semantic + daeegg_cat.info() << "Ignoring effect referenced by material with semantic " << semantic << " because it has no common profile" << endl; } else { daeegg_cat.spam() << "Processing effect, material semantic is " << semantic << endl; // Set the material parameters egg_material->set_amb(TO_COLOR(effect_common->GetAmbientColor())); - ////TODO: find a better way for transparency + ////We already process transparency using blend modes //LVecBase4f diffuse = TO_COLOR(effect_common->GetDiffuseColor()); //diffuse.set_w(diffuse.get_w() * (1.0f - effect_common->GetOpacity())); //egg_material->set_diff(diffuse); @@ -149,11 +153,8 @@ process_texture_bucket(const string semantic, const FCDEffectStandard* effect_co // Find a set of UV coordinates const FCDEffectParameterInt* uvset = effect_common->GetTexture(bucket, tx)->GetSet(); if (uvset != NULL) { - if (_materials[semantic]->_uvsets.count(uvset->GetValue()) == 0) { - daeegg_cat.warning() << "Texture references a nonexisting UV coordinate set!" << endl; - } else { - egg_texture->set_uv_name(_materials[semantic]->_uvsets[uvset->GetValue()]); - } + daeegg_cat.debug() << "Texture has uv name '" << FROM_FSTRING(uvset->GetSemantic()) << "'\n"; + egg_texture->set_uv_name(FROM_FSTRING(uvset->GetSemantic())); } // Apply sampler stuff if (sampler != NULL) { @@ -243,14 +244,34 @@ apply_to(const string semantic, const PT(EggGroup) to) { //////////////////////////////////////////////////////////////////// // Function: DaeMaterials::get_uvset_name // Access: Public -// Description: Returns the name of the uvset with the specified -// FCollada input set, or an empty string if the given -// material has no input set. +// Description: Returns the semantic of the uvset with the +// specified input set, or an empty string if the +// given material has no input set. //////////////////////////////////////////////////////////////////// const string DaeMaterials:: -get_uvset_name(const string semantic, int32 input_set) { - if (_materials.count(semantic) > 0 && _materials[semantic]->_uvsets.count(input_set)) { - return _materials[semantic]->_uvsets[input_set]; +get_uvset_name(const string semantic, FUDaeGeometryInput::Semantic input_semantic, int32 input_set) { + if (_materials.count(semantic) > 0) { + if (input_set == -1 && _materials[semantic]->_uvsets.size() == 1) { + return _materials[semantic]->_uvsets[0]->_semantic; + } else { + for (int i = 0; i < _materials[semantic]->_uvsets.size(); ++i) { + if (_materials[semantic]->_uvsets[i]->_input_set == input_set && + _materials[semantic]->_uvsets[i]->_input_semantic == input_semantic) { + return _materials[semantic]->_uvsets[i]->_semantic; + } + } + // If we can't find it, let's look again, but don't care for the + // input_semantic this time. The reason for this is that some tools + // export textangents and texbinormals bound to a uvset with input + // semantic TEXCOORD. + for (int i = 0; i < _materials[semantic]->_uvsets.size(); ++i) { + if (_materials[semantic]->_uvsets[i]->_input_set == input_set) { + daeegg_cat.info() << "Using uv set with non-matching input semantic\n"; + return _materials[semantic]->_uvsets[i]->_semantic; + } + } + daeegg_cat.warning() << "No uv set binding found for input set " << input_set << "\n"; + } } return ""; } @@ -387,6 +408,22 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, Colorf transparent, doub blend->_operand_a = EggGroup::BO_one; } } + if (blend->_operand_b == EggGroup::BO_constant_color) { + if ((blend->_color[0] == 0) && (blend->_color[1] == 0) && (blend->_color[2] == 0) && (blend->_color[3] == 0)) { + blend->_operand_b = EggGroup::BO_zero; + } + if ((blend->_color[0] == 1) && (blend->_color[1] == 1) && (blend->_color[2] == 1) && (blend->_color[3] == 1)) { + blend->_operand_b = EggGroup::BO_one; + } + } + if (blend->_operand_a == EggGroup::BO_one_minus_constant_color) { + if ((blend->_color[0] == 0) && (blend->_color[1] == 0) && (blend->_color[2] == 0) && (blend->_color[3] == 0)) { + blend->_operand_a = EggGroup::BO_one; + } + if ((blend->_color[0] == 1) && (blend->_color[1] == 1) && (blend->_color[2] == 1) && (blend->_color[3] == 1)) { + blend->_operand_a = EggGroup::BO_zero; + } + } if (blend->_operand_b == EggGroup::BO_one_minus_constant_color) { if ((blend->_color[0] == 0) && (blend->_color[1] == 0) && (blend->_color[2] == 0) && (blend->_color[3] == 0)) { blend->_operand_b = EggGroup::BO_one; diff --git a/pandatool/src/daeegg/daeMaterials.h b/pandatool/src/daeegg/daeMaterials.h index 2303937762..3fbb7255ee 100755 --- a/pandatool/src/daeegg/daeMaterials.h +++ b/pandatool/src/daeegg/daeMaterials.h @@ -46,7 +46,7 @@ public: void add_material_instance(const FCDMaterialInstance* instance); void apply_to(const string semantic, const PT(EggPrimitive) to); void apply_to(const string semantic, const PT(EggGroup) to); - const string get_uvset_name(const string semantic, int32 input_set); + const string get_uvset_name(const string semantic, FUDaeGeometryInput::Semantic input_semantic, int32 input_set); static EggTexture::TextureType convert_texture_type(const FCDEffectParameterSampler::SamplerType orig_type); static EggTexture::WrapMode convert_wrap_mode(const FUDaeTextureWrapMode::WrapMode orig_mode); @@ -61,12 +61,19 @@ private: EggGroup::BlendOperand _operand_b; }; + // Holds information to bind texcoord inputs to textures. + struct DaeVertexInputBinding : public ReferenceCount { + int32 _input_set; + FUDaeGeometryInput::Semantic _input_semantic; + string _semantic; + }; + // Holds stuff for an individual material. struct DaeMaterial : public ReferenceCount { pvector _egg_textures; PT_EggMaterial _egg_material; bool _double_sided; - pmap _uvsets; + pvector _uvsets; PT(DaeBlendSettings) _blend; }; diff --git a/pandatool/src/daeegg/daeToEggConverter.cxx b/pandatool/src/daeegg/daeToEggConverter.cxx index b0d53a12d8..ef2bd299b7 100755 --- a/pandatool/src/daeegg/daeToEggConverter.cxx +++ b/pandatool/src/daeegg/daeToEggConverter.cxx @@ -362,10 +362,21 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* const FCDGeometryPolygonsInput* tinput = polygons->FindInput(FUDaeGeometryInput::TEXTANGENT); const uint32* tindices; if (tinput != NULL) tindices = tinput->GetIndices(); - // Get a name for potential texture coordinate sets - string uvsetname (""); + // Get a name for potential coordinate sets + string tcsetname (""); if (materials != NULL && tcinput != NULL) { - uvsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), tcinput->GetSet()); + daeegg_cat.debug() << "Assigning texcoord set " << tcinput->GetSet() << " to semantic " << FROM_FSTRING(polygons->GetMaterialSemantic()) << "\n"; + tcsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXCOORD, tcinput->GetSet()); + } + string tbsetname (""); + if (materials != NULL && binput != NULL) { + daeegg_cat.debug() << "Assigning texbinormal set " << binput->GetSet() << " to semantic " << FROM_FSTRING(polygons->GetMaterialSemantic()) << "\n"; + tbsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXBINORMAL, binput->GetSet()); + } + string ttsetname (""); + if (materials != NULL && tinput != NULL) { + daeegg_cat.debug() << "Assigning textangent set " << tinput->GetSet() << " to semantic " << FROM_FSTRING(polygons->GetMaterialSemantic()) << "\n"; + ttsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXTANGENT, tinput->GetSet()); } // Loop through the indices and add the vertices. for (size_t ix = 0; ix < pinput->GetIndexCount(); ++ix) { @@ -383,9 +394,9 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* assert(tcsource->GetStride() == 2 || tcsource->GetStride() == 3); data = &tcsource->GetData()[tcindices[ix]*tcsource->GetStride()]; if (tcsource->GetStride() == 2) { - vertex->set_uv(uvsetname, LPoint2d(data[0], data[1])); + vertex->set_uv(tcsetname, LPoint2d(data[0], data[1])); } else { - vertex->set_uvw(uvsetname, LPoint3d(data[0], data[1], data[2])); + vertex->set_uvw(tcsetname, LPoint3d(data[0], data[1], data[2])); } } // Process the color @@ -396,28 +407,23 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* } // Possibly add a UV object if ((bsource != NULL && binput != NULL) || (tsource != NULL && tinput != NULL)) { - PT(EggVertexUV) vertex_uv; - if (tcsource != NULL && tcinput != NULL) { - assert(tcsource->GetStride() == 2 || tcsource->GetStride() == 3); - data = &tcsource->GetData()[tcindices[ix]*tcsource->GetStride()]; - if (tcsource->GetStride() == 2) { - vertex_uv = new EggVertexUV(uvsetname, TexCoordd(data[0], data[1])); - } else { - vertex_uv = new EggVertexUV(uvsetname, TexCoord3d(data[0], data[1], data[2])); - } - } else { - vertex_uv = new EggVertexUV(uvsetname, TexCoordd()); - } - vertex->set_uv_obj(vertex_uv); if (bsource != NULL && binput != NULL) { assert(bsource->GetStride() == 3); data = &bsource->GetData()[bindices[ix]*3]; - vertex_uv->set_binormal(LVecBase3d(data[0], data[1], data[2])); + PT(EggVertexUV) uv_obj = vertex->modify_uv_obj(tbsetname); + if (uv_obj == NULL) { + uv_obj = new EggVertexUV(tbsetname, TexCoordd()); + } + uv_obj->set_binormal(LVecBase3d(data[0], data[1], data[2])); } if (tsource != NULL && tinput != NULL) { assert(tsource->GetStride() == 3); data = &tsource->GetData()[tindices[ix]*3]; - vertex_uv->set_tangent(LVecBase3d(data[0], data[1], data[2])); + PT(EggVertexUV) uv_obj = vertex->modify_uv_obj(ttsetname); + if (uv_obj == NULL) { + uv_obj = new EggVertexUV(ttsetname, TexCoordd()); + } + uv_obj->set_tangent(LVecBase3d(data[0], data[1], data[2])); } } vertex->transform(parent->get_node_to_vertex());