18 #include <FCDocument/FCDocument.h> 19 #include <FCDocument/FCDMaterial.h> 20 #include <FCDocument/FCDEffect.h> 21 #include <FCDocument/FCDTexture.h> 22 #include <FCDocument/FCDEffectParameterSampler.h> 23 #include <FCDocument/FCDImage.h> 35 #define luminance(c) ((c[0] * 0.212671 + c[1] * 0.715160 + c[2] * 0.072169)) 41 DaeMaterials(
const FCDGeometryInstance* geometry_instance) {
42 for (
size_t mi = 0; mi < geometry_instance->GetMaterialInstanceCount(); ++mi) {
51 nassertv(instance !=
nullptr);
52 const string semantic (FROM_FSTRING(instance->GetSemantic()));
53 if (_materials.count(semantic) > 0) {
54 daeegg_cat.warning() <<
"Ignoring duplicate material with semantic " << semantic << endl;
57 _materials[semantic] =
new DaeMaterial();
60 for (
size_t vib = 0; vib < instance->GetVertexInputBindingCount(); ++vib) {
61 const FCDMaterialInstanceBindVertexInput* mivib = instance->GetVertexInputBinding(vib);
62 assert(mivib !=
nullptr);
63 PT(DaeVertexInputBinding) bvi =
new DaeVertexInputBinding();
64 bvi->_input_set = mivib->inputSet;
65 #if FCOLLADA_VERSION >= 0x00030005 66 bvi->_input_semantic = mivib->GetInputSemantic();
67 bvi->_semantic = *mivib->semantic;
69 bvi->_input_semantic = mivib->inputSemantic;
70 bvi->_semantic = FROM_FSTRING(mivib->semantic);
72 _materials[semantic]->_uvsets.push_back(bvi);
76 daeegg_cat.spam() <<
"Trying to process material with semantic " << semantic << endl;
77 PT_EggMaterial egg_material =
new EggMaterial(semantic);
79 const FCDEffect* effect = instance->GetMaterial()->GetEffect();
80 if (effect ==
nullptr) {
81 daeegg_cat.debug() <<
"Ignoring material (semantic: " << semantic <<
") without assigned effect" << endl;
84 const FCDEffectStandard* effect_common = (FCDEffectStandard *)effect->FindProfile(FUDaeProfileType::COMMON);
85 if (effect_common ==
nullptr) {
86 daeegg_cat.info() <<
"Ignoring effect referenced by material with semantic " << semantic
87 <<
" because it has no common profile" << endl;
89 daeegg_cat.spam() <<
"Processing effect, material semantic is " << semantic << endl;
91 egg_material->set_amb(TO_COLOR(effect_common->GetAmbientColor()));
96 egg_material->set_diff(TO_COLOR(effect_common->GetDiffuseColor()));
97 egg_material->set_emit(TO_COLOR(effect_common->GetEmissionColor()) * effect_common->GetEmissionFactor());
98 egg_material->set_shininess(effect_common->GetShininess());
99 egg_material->set_spec(TO_COLOR(effect_common->GetSpecularColor()));
101 process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::DIFFUSE, EggTexture::ET_modulate);
102 process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::BUMP, EggTexture::ET_normal);
103 process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::SPECULAR, EggTexture::ET_modulate_gloss);
104 process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::SPECULAR_LEVEL, EggTexture::ET_gloss);
105 process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::TRANSPARENT, EggTexture::ET_unspecified, EggTexture::F_alpha);
106 process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::EMISSION, EggTexture::ET_add);
107 #if FCOLLADA_VERSION < 0x00030005 108 process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::OPACITY, EggTexture::ET_unspecified, EggTexture::F_alpha);
111 _materials[semantic]->_blend = convert_blend(effect_common->GetTransparencyMode(),
112 TO_COLOR(effect_common->GetTranslucencyColor()),
113 effect_common->GetTranslucencyFactor());
116 process_extra(semantic, effect->GetExtra());
118 daeegg_cat.spam() <<
"Found " << egg_textures.size() <<
" textures in material" << endl;
119 _materials[semantic]->_egg_material = egg_material;
127 process_texture_bucket(
const string semantic,
const FCDEffectStandard* effect_common, FUDaeTextureChannel::Channel bucket, EggTexture::EnvType envtype, EggTexture::Format format) {
128 for (
size_t tx = 0; tx < effect_common->GetTextureCount(bucket); ++tx) {
129 const FCDImage* image = effect_common->GetTexture(bucket, tx)->GetImage();
130 if (image ==
nullptr) {
131 daeegg_cat.warning() <<
"Texture references a nonexisting image!" << endl;
133 const FCDEffectParameterSampler* sampler = effect_common->GetTexture(bucket, tx)->GetSampler();
137 if (image->GetDocument()) {
143 daeegg_cat.debug() <<
"Found texture with path " << texpath << endl;
150 const FCDEffectParameterInt* uvset = effect_common->GetTexture(bucket, tx)->GetSet();
151 if (uvset !=
nullptr) {
152 daeegg_cat.debug() <<
"Texture has uv name '" << FROM_FSTRING(uvset->GetSemantic()) <<
"'\n";
153 string uvset_semantic (FROM_FSTRING(uvset->GetSemantic()));
156 for (
size_t i = 0; i < _materials[semantic]->_uvsets.size(); ++i) {
157 if (_materials[semantic]->_uvsets[i]->_semantic == uvset_semantic) {
158 egg_texture->set_uv_name(uvset_semantic);
164 if (sampler !=
nullptr) {
167 if (sampler->GetSamplerType() != FCDEffectParameterSampler::SAMPLER1D) {
170 if (sampler->GetSamplerType() == FCDEffectParameterSampler::SAMPLER3D) {
175 if (envtype != EggTexture::ET_unspecified) {
176 egg_texture->set_env_type(envtype);
178 if (format != EggTexture::F_unspecified) {
179 egg_texture->set_format(format);
182 _materials[semantic]->_egg_textures.push_back(egg_texture);
192 process_extra(
const string semantic,
const FCDExtra* extra) {
193 if (extra ==
nullptr)
return;
194 const FCDEType* etype = extra->GetDefaultType();
195 if (etype ==
nullptr)
return;
196 for (
size_t et = 0; et < etype->GetTechniqueCount(); ++et) {
197 const FCDENode* enode = ((
const FCDENode*)(etype->GetTechnique(et)))->FindChildNode(
"double_sided");
198 if (enode !=
nullptr) {
199 string content =
trim(enode->GetContent());
200 if (content ==
"1" || content ==
"true") {
201 _materials[semantic]->_double_sided =
true;
202 }
else if (content ==
"0" || content ==
"false") {
203 _materials[semantic]->_double_sided =
false;
205 daeegg_cat.warning() <<
"Expected <double_sided> tag to be either 1 or 0, found '" << content <<
"' instead" << endl;
216 if (_materials.count(semantic) > 0) {
219 daeegg_cat.spam() <<
"Applying texture " << (*it)->get_name() <<
" from material with semantic " << semantic << endl;
231 if (_materials.count(semantic) > 0) {
232 PT(DaeBlendSettings) blend = _materials[semantic]->_blend;
233 if (blend && blend->_enabled) {
234 to->set_blend_mode(EggGroup::BM_add);
235 to->set_blend_color(blend->_color);
236 if (invert_transparency) {
237 to->set_blend_operand_a(blend->_operand_b);
238 to->set_blend_operand_b(blend->_operand_a);
240 to->set_blend_operand_a(blend->_operand_a);
241 to->set_blend_operand_b(blend->_operand_b);
243 }
else if (blend && invert_transparency) {
244 to->set_blend_mode(EggGroup::BM_add);
245 to->set_blend_color(blend->_color);
246 to->set_blend_operand_a(blend->_operand_b);
247 to->set_blend_operand_b(blend->_operand_a);
257 get_uvset_name(
const string semantic, FUDaeGeometryInput::Semantic input_semantic, int32 input_set) {
258 if (_materials.count(semantic) > 0) {
259 if (input_set == -1 && _materials[semantic]->_uvsets.size() == 1) {
260 return _materials[semantic]->_uvsets[0]->_semantic;
262 for (
size_t i = 0; i < _materials[semantic]->_uvsets.size(); ++i) {
263 if (_materials[semantic]->_uvsets[i]->_input_set == input_set &&
264 _materials[semantic]->_uvsets[i]->_input_semantic == input_semantic) {
265 return _materials[semantic]->_uvsets[i]->_semantic;
272 for (
size_t i = 0; i < _materials[semantic]->_uvsets.size(); ++i) {
273 if (_materials[semantic]->_uvsets[i]->_input_set == input_set) {
274 daeegg_cat.debug() <<
"Using uv set with non-matching input semantic " << _materials[semantic]->_uvsets[i]->_semantic <<
"\n";
275 return _materials[semantic]->_uvsets[i]->_semantic;
278 daeegg_cat.debug() <<
"No uv set binding found for input set " << input_set <<
"\n";
291 case FCDEffectParameterSampler::SAMPLER1D:
292 return EggTexture::TT_1d_texture;
293 case FCDEffectParameterSampler::SAMPLER2D:
294 return EggTexture::TT_2d_texture;
295 case FCDEffectParameterSampler::SAMPLER3D:
296 return EggTexture::TT_3d_texture;
297 case FCDEffectParameterSampler::SAMPLERCUBE:
298 return EggTexture::TT_cube_map;
300 daeegg_cat.warning() <<
"Invalid sampler type found" << endl;
302 return EggTexture::TT_unspecified;
311 case FUDaeTextureWrapMode::NONE:
313 return EggTexture::WM_unspecified;
314 case FUDaeTextureWrapMode::WRAP:
315 return EggTexture::WM_repeat;
316 case FUDaeTextureWrapMode::MIRROR:
317 return EggTexture::WM_mirror;
318 case FUDaeTextureWrapMode::CLAMP:
319 return EggTexture::WM_clamp;
320 case FUDaeTextureWrapMode::BORDER:
321 return EggTexture::WM_border_color;
322 case FUDaeTextureWrapMode::UNKNOWN:
323 return EggTexture::WM_unspecified;
325 daeegg_cat.warning() <<
"Invalid wrap mode found: " << FUDaeTextureWrapMode::ToString(orig_mode) << endl;
327 return EggTexture::WM_unspecified;
337 case FUDaeTextureFilterFunction::NONE:
339 return EggTexture::FT_unspecified;
340 case FUDaeTextureFilterFunction::NEAREST:
341 return EggTexture::FT_nearest;
342 case FUDaeTextureFilterFunction::LINEAR:
343 return EggTexture::FT_linear;
344 case FUDaeTextureFilterFunction::NEAREST_MIPMAP_NEAREST:
345 return EggTexture::FT_nearest_mipmap_nearest;
346 case FUDaeTextureFilterFunction::LINEAR_MIPMAP_NEAREST:
347 return EggTexture::FT_linear_mipmap_nearest;
348 case FUDaeTextureFilterFunction::NEAREST_MIPMAP_LINEAR:
349 return EggTexture::FT_nearest_mipmap_linear;
350 case FUDaeTextureFilterFunction::LINEAR_MIPMAP_LINEAR:
351 return EggTexture::FT_linear_mipmap_linear;
352 case FUDaeTextureFilterFunction::UNKNOWN:
353 return EggTexture::FT_unspecified;
355 daeegg_cat.warning() <<
"Unknown filter type found: " << FUDaeTextureFilterFunction::ToString(orig_type) << endl;
357 return EggTexture::FT_unspecified;
363 PT(DaeMaterials::DaeBlendSettings) DaeMaterials::
364 convert_blend(FCDEffectStandard::TransparencyMode mode,
const LColor &transparent,
double transparency) {
366 PT(DaeBlendSettings) blend =
new DaeBlendSettings();
367 blend->_enabled =
true;
368 blend->_color = LColor::zero();
369 blend->_operand_a = EggGroup::BO_unspecified;
370 blend->_operand_b = EggGroup::BO_unspecified;
373 if (mode == FCDEffectStandard::A_ONE) {
374 double value = transparent[3] * transparency;
375 blend->_color = LColor(value, value, value, value);
376 }
else if (mode == FCDEffectStandard::RGB_ZERO) {
377 blend->_color = transparent * transparency;
378 blend->_color[3] = luminance(blend->_color);
380 daeegg_cat.error() <<
"Unknown opaque type found!" << endl;
381 blend->_enabled =
false;
386 if (mode == FCDEffectStandard::RGB_ZERO) {
387 blend->_operand_a = EggGroup::BO_one_minus_constant_color;
388 blend->_operand_b = EggGroup::BO_constant_color;
389 }
else if (mode == FCDEffectStandard::A_ONE) {
390 blend->_operand_a = EggGroup::BO_constant_color;
391 blend->_operand_b = EggGroup::BO_one_minus_constant_color;
393 daeegg_cat.error() <<
"Unknown opaque type found!" << endl;
394 blend->_enabled =
false;
399 if (blend->_operand_a == EggGroup::BO_constant_color) {
400 if (blend->_color == LColor::zero()) {
401 blend->_operand_a = EggGroup::BO_zero;
402 }
else if (blend->_color == LColor(1, 1, 1, 1)) {
403 blend->_operand_a = EggGroup::BO_one;
406 if (blend->_operand_b == EggGroup::BO_constant_color) {
407 if (blend->_color == LColor::zero()) {
408 blend->_operand_b = EggGroup::BO_zero;
409 }
else if (blend->_color == LColor(1, 1, 1, 1)) {
410 blend->_operand_b = EggGroup::BO_one;
413 if (blend->_operand_a == EggGroup::BO_one_minus_constant_color) {
414 if (blend->_color == LColor::zero()) {
415 blend->_operand_a = EggGroup::BO_one;
416 }
else if (blend->_color == LColor(1, 1, 1, 1)) {
417 blend->_operand_a = EggGroup::BO_zero;
420 if (blend->_operand_b == EggGroup::BO_one_minus_constant_color) {
421 if (blend->_color == LColor::zero()) {
422 blend->_operand_b = EggGroup::BO_one;
423 }
else if (blend->_color == LColor(1, 1, 1, 1)) {
424 blend->_operand_b = EggGroup::BO_zero;
429 if (blend->_operand_a == EggGroup::BO_one && blend->_operand_b == EggGroup::BO_zero) {
430 blend->_enabled =
false;
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
std::string get_dirname() const
Returns the directory part of the filename.
void add_texture(EggTexture *texture)
Applies the indicated texture to the primitive.
Defines a texture map that may be applied to geometry.
static EggTexture::FilterType convert_filter_type(const FUDaeTextureFilterFunction::FilterFunction orig_type)
Converts an FCollada filter function to the EggTexture wrap type equivalent.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
set_bface_flag
Sets the backfacing flag of the polygon.
void add_material_instance(const FCDMaterialInstance *instance)
Adds a material instance.
bool make_canonical()
Converts this filename to a canonical name by replacing the directory part with the fully-qualified d...
set_material
Applies the indicated material to the primitive.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string to_os_generic() const
This is similar to to_os_specific(), but it is designed to generate a filename that can be understood...
PT(DaeMaterials::DaeBlendSettings) DaeMaterials
Converts collada blend attribs to Panda's equivalents.
void apply_to_primitive(const std::string semantic, const PT(EggPrimitive) to)
Applies the stuff to the given EggPrimitive.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
The name of a file, such as a texture file or an Egg file.
static EggTexture::WrapMode convert_wrap_mode(const FUDaeTextureWrapMode::WrapMode orig_mode)
Converts an FCollada wrap mode to the EggTexture wrap mode equivalent.
static EggTexture::TextureType convert_texture_type(const FCDEffectParameterSampler::SamplerType orig_type)
Converts an FCollada sampler type to the EggTexture texture type equivalent.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string trim(const string &str)
Returns a new string representing the contents of the given string with both leading and trailing whi...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool make_relative_to(Filename directory, bool allow_backups=true)
Adjusts this filename, which must be a fully-specified pathname beginning with a slash,...
const std::string get_uvset_name(const std::string semantic, FUDaeGeometryInput::Semantic input_semantic, int32 input_set)
Returns the semantic of the uvset with the specified input set, or an empty string if the given mater...
TypeHandle is the identifier used to differentiate C++ class types.
void apply_to_group(const std::string semantic, const PT(EggGroup) to, bool invert_transparency=false)
Applies the colorblend stuff to the given EggGroup.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...