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;
static EggTexture::TextureType convert_texture_type(const FCDEffectParameterSampler::SamplerType orig_type)
Converts an FCollada sampler type to the EggTexture texture type equivalent.
void add_material_instance(const FCDMaterialInstance *instance)
Adds a material instance.
static EggTexture::WrapMode convert_wrap_mode(const FUDaeTextureWrapMode::WrapMode orig_mode)
Converts an FCollada wrap mode to the EggTexture wrap mode equivalent.
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...
void apply_to_group(const std::string semantic, const PT(EggGroup) to, bool invert_transparency=false)
Applies the colorblend stuff to the given EggGroup.
void apply_to_primitive(const std::string semantic, const PT(EggPrimitive) to)
Applies the stuff to the given EggPrimitive.
static EggTexture::FilterType convert_filter_type(const FUDaeTextureFilterFunction::FilterFunction orig_type)
Converts an FCollada filter function to the EggTexture wrap type equivalent.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
set_bface_flag
Sets the backfacing flag of the polygon.
set_material
Applies the indicated material to the primitive.
void add_texture(EggTexture *texture)
Applies the indicated texture to the primitive.
Defines a texture map that may be applied to geometry.
The name of a file, such as a texture file or an Egg file.
bool make_canonical()
Converts this filename to a canonical name by replacing the directory part with the fully-qualified d...
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,...
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...
bool make_relative_to(Filename directory, bool allow_backups=true)
Adjusts this filename, which must be a fully-specified pathname beginning with a slash,...
std::string get_dirname() const
Returns the directory part of the filename.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(DaeMaterials::DaeBlendSettings) DaeMaterials
Converts collada blend attribs to Panda's equivalents.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.