Browse Source

Overhauled UV-handling in order to have better support for multiple UV sets, I hope

rdb 17 years ago
parent
commit
07d83f7a9c

+ 52 - 15
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;

+ 9 - 2
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<PT_EggTexture> _egg_textures;
     PT_EggMaterial _egg_material;
     bool _double_sided;
-    pmap<int32, string> _uvsets;
+    pvector<PT(DaeVertexInputBinding)> _uvsets;
     PT(DaeBlendSettings) _blend;
   };
   

+ 26 - 20
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());