mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
Added Collada converter
This commit is contained in:
parent
5616517d99
commit
7e1496141f
27
pandatool/src/daeegg/Sources.pp
Executable file
27
pandatool/src/daeegg/Sources.pp
Executable file
@ -0,0 +1,27 @@
|
||||
#define BUILD_DIRECTORY $[HAVE_FCOLLADA]
|
||||
|
||||
#begin lib_target
|
||||
#define USE_PACKAGES fcollada
|
||||
#define TARGET daeegg
|
||||
#define LOCAL_LIBS converter pandatoolbase
|
||||
#define OTHER_LIBS \
|
||||
egg:c pandaegg:m \
|
||||
pandabase:c express:c pandaexpress:m \
|
||||
pipeline:c mathutil:c linmath:c putil:c event:c \
|
||||
panda:m \
|
||||
interrogatedb:c prc:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m
|
||||
|
||||
#define SOURCES \
|
||||
config_daeegg.cxx config_daeegg.h \
|
||||
daeToEggConverter.cxx daeToEggConverter.h \
|
||||
daeCharacter.cxx daeCharacter.h \
|
||||
daeMaterials.cxx daeMaterials.h \
|
||||
pre_fcollada_include.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_daeegg.h daeToEggConverter.h \
|
||||
daeCharacter.h daeMaterials.h \
|
||||
pre_fcollada_include.h
|
||||
|
||||
#end lib_target
|
47
pandatool/src/daeegg/config_daeegg.cxx
Normal file
47
pandatool/src/daeegg/config_daeegg.cxx
Normal file
@ -0,0 +1,47 @@
|
||||
// Filename: config_daeegg.cxx
|
||||
// Created by: pro-rsoft (30Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_daeegg.h"
|
||||
#include "daeCharacter.h"
|
||||
#include "daeMaterials.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_daeegg);
|
||||
NotifyCategoryDef(daeegg, "");
|
||||
|
||||
ConfigureFn(config_daeegg) {
|
||||
init_libdaeegg();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libdaeegg
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes in
|
||||
// this library can be used. Normally it will be
|
||||
// called by the static initializers and need not be
|
||||
// called explicitly, but special cases exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libdaeegg() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
DaeCharacter::init_type();
|
||||
DaeMaterials::init_type();
|
||||
}
|
||||
|
25
pandatool/src/daeegg/config_daeegg.h
Normal file
25
pandatool/src/daeegg/config_daeegg.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Filename: config_daeegg.h
|
||||
// Created by: pro-rsoft (30Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_DAEEGG_H
|
||||
#define CONFIG_DAEEGG_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
|
||||
NotifyCategoryDeclNoExport(daeegg);
|
||||
|
||||
extern void init_libdaeegg();
|
||||
|
||||
#endif
|
107
pandatool/src/daeegg/daeCharacter.cxx
Normal file
107
pandatool/src/daeegg/daeCharacter.cxx
Normal file
@ -0,0 +1,107 @@
|
||||
// Filename: daeCharacter.cxx
|
||||
// Created by: pro-rsoft (24Nov08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "daeCharacter.h"
|
||||
#include "config_daeegg.h"
|
||||
#include "pt_EggVertex.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDController.h"
|
||||
#include "FCDocument/FCDSceneNodeTools.h"
|
||||
|
||||
TypeHandle DaeCharacter::_type_handle;
|
||||
|
||||
// Useful conversion stuff
|
||||
#define TO_VEC3(v) (LVecBase3d(v[0], v[1], v[2]))
|
||||
#define TO_VEC4(v) (LVecBase4d(v[0], v[1], v[2], v[3]))
|
||||
#define TO_COLOR(v) (Colorf(v[0], v[1], v[2], v[3]))
|
||||
#define FROM_VEC3(v) (FMVector3(v[0], v[1], v[2]))
|
||||
#define FROM_VEC4(v) (FMVector4(v[0], v[1], v[2], v[3]))
|
||||
#define FROM_MAT4(v) (FMMatrix44(v.getData()))
|
||||
#define FROM_FSTRING(fs) (string(fs.c_str()))
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeCharacter::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DaeCharacter::
|
||||
DaeCharacter(const string name, const FCDControllerInstance* controller_instance) {
|
||||
_controller_instance = (FCDControllerInstance*) controller_instance;
|
||||
_name = name;
|
||||
_frame_rate = 0;
|
||||
_skin_controller = NULL;
|
||||
// If it's a skin controller, add the controller joints.
|
||||
FCDController* controller = (FCDController*) controller_instance->GetEntity();
|
||||
if (controller == NULL) return;
|
||||
if (controller->IsSkin()) {
|
||||
_skin_controller = controller->GetSkinController();
|
||||
if (_skin_controller == NULL) return;
|
||||
for (size_t j = 0; j < _skin_controller->GetJointCount(); ++j) {
|
||||
_controller_joints[FROM_FSTRING(_skin_controller->GetJoint(j)->GetId())] = (FCDSkinControllerJoint*) _skin_controller->GetJoint(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeCharacter::as_egg_bundle
|
||||
// Access: Public
|
||||
// Description: Returns the character as a <Bundle> element,
|
||||
// suited for the animation table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(EggTable) DaeCharacter::
|
||||
as_egg_bundle() {
|
||||
PT(EggTable) bundle = new EggTable(_name);
|
||||
bundle->set_table_type(EggTable::TT_bundle);
|
||||
PT(EggTable) skeleton = new EggTable("<skeleton>");
|
||||
skeleton->set_table_type(EggTable::TT_table);
|
||||
bundle->add_child(skeleton);
|
||||
// Loop through the joint hierarchy
|
||||
FCDSceneNodeList roots = _controller_instance->FindSkeletonNodes();
|
||||
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
|
||||
process_joint(skeleton, *it);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeCharacter::process_joint
|
||||
// Access: Public
|
||||
// Description: Processes a joint node and its transforms.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DaeCharacter::
|
||||
process_joint(PT(EggTable) parent, FCDSceneNode* node) {
|
||||
nassertv(node != NULL);
|
||||
string node_id = FROM_FSTRING(node->GetDaeId());
|
||||
PT(EggTable) joint = new EggTable(node_id);
|
||||
joint->set_table_type(EggTable::TT_table);
|
||||
parent->add_child(joint);
|
||||
PT(EggXfmSAnim) xform = new EggXfmSAnim("xform");
|
||||
joint->add_child(xform);
|
||||
xform->set_fps(_frame_rate);
|
||||
// Generate the sampled animation and loop through the matrices
|
||||
FCDSceneNodeTools::GenerateSampledAnimation(node);
|
||||
FMMatrix44List matrices = FCDSceneNodeTools::GetSampledAnimationMatrices();
|
||||
for (FMMatrix44List::const_iterator it = matrices.begin(); it != matrices.end(); ++it) {
|
||||
LMatrix4d matr = DAEToEggConverter::convert_matrix(*it);
|
||||
assert(xform->add_data(matr));
|
||||
}
|
||||
// Loop through the children joints
|
||||
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
||||
if (node->GetChild(ch)->IsJoint()) {
|
||||
process_joint(joint, node->GetChild(ch));
|
||||
}
|
||||
}
|
||||
}
|
65
pandatool/src/daeegg/daeCharacter.h
Normal file
65
pandatool/src/daeegg/daeCharacter.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Filename: daeCharacter.h
|
||||
// Created by: pro-rsoft (24Nov08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typeHandle.h"
|
||||
#include "eggTable.h"
|
||||
#include "daeToEggConverter.h"
|
||||
|
||||
#include "pre_fcollada_include.h"
|
||||
#include "FCollada.h"
|
||||
#include "FCDocument/FCDSceneNode.h"
|
||||
#include "FCDocument/FCDControllerInstance.h"
|
||||
#include "FCDocument/FCDSkinController.h"
|
||||
|
||||
#ifndef DAECHARACTER_H
|
||||
#define DAECHARACTER_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DaeCharacter
|
||||
// Description : Class representing an animated character.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class DaeCharacter : public TypedReferenceCount {
|
||||
public:
|
||||
DaeCharacter(const string name, const FCDControllerInstance* controller_instance);
|
||||
PT(EggTable) as_egg_bundle();
|
||||
void process_joint(PT(EggTable) parent, FCDSceneNode* node);
|
||||
|
||||
private:
|
||||
int _frame_rate;
|
||||
string _name;
|
||||
FCDControllerInstance* _controller_instance;
|
||||
FCDSkinController* _skin_controller;
|
||||
pmap<string, FCDSkinControllerJoint*> _controller_joints;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "DaeCharacter",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#endif
|
403
pandatool/src/daeegg/daeMaterials.cxx
Executable file
403
pandatool/src/daeegg/daeMaterials.cxx
Executable file
@ -0,0 +1,403 @@
|
||||
// Filename: daeMaterials.cxx
|
||||
// Created by: pro-rsoft (03Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "daeMaterials.h"
|
||||
#include "config_daeegg.h"
|
||||
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDMaterial.h"
|
||||
#include "FCDocument/FCDEffect.h"
|
||||
#include "FCDocument/FCDTexture.h"
|
||||
#include "FCDocument/FCDEffectParameterSampler.h"
|
||||
#include "FCDocument/FCDImage.h"
|
||||
|
||||
#include "filename.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
TypeHandle DaeMaterials::_type_handle;
|
||||
|
||||
// Useful conversion stuff
|
||||
#define CONV_VEC3(v) (LVecBase3d(v[0], v[1], v[2]))
|
||||
#define CONV_VEC4(v) (LVecBase4d(v[0], v[1], v[2], v[3]))
|
||||
#define CONV_COLOR(v) (Colorf(v[0], v[1], v[2], v[3]))
|
||||
#define FROM_FSTRING(fs) (string(fs.c_str()))
|
||||
|
||||
// luminance function, based on the ISO/CIE color standards
|
||||
// see ITU-R Recommendation BT.709-4
|
||||
#define luminance(c) ((c[0] * 0.212671 + c[1] * 0.715160 + c[2] * 0.072169))
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DaeMaterials::
|
||||
DaeMaterials(const FCDGeometryInstance* geometry_instance) {
|
||||
for (size_t mi = 0; mi < geometry_instance->GetMaterialInstanceCount(); ++mi) {
|
||||
add_material_instance(geometry_instance->GetMaterialInstance(mi));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::add_material_instance
|
||||
// Access: Public
|
||||
// Description: Adds a material instance. Normally automatically
|
||||
// done by constructor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) {
|
||||
nassertv(instance != NULL);
|
||||
const string semantic (FROM_FSTRING(instance->GetSemantic()));
|
||||
if (_materials.count(semantic) > 0) {
|
||||
daeegg_cat.warning() << "Ignoring duplicate material with semantic" << semantic << endl;
|
||||
return;
|
||||
}
|
||||
_materials[semantic] = new DaeMaterial();
|
||||
|
||||
// Load in the uvsets
|
||||
for (size_t vib = 0; vib < instance->GetVertexInputBindingCount(); ++vib) {
|
||||
const FCDMaterialInstanceBindVertexInput* mivib = instance->GetVertexInputBinding(vib);
|
||||
assert(mivib != NULL);
|
||||
_materials[semantic]->_uvsets[mivib->inputSet] = FROM_FSTRING(mivib->semantic);
|
||||
}
|
||||
|
||||
// Handle the material stuff
|
||||
daeegg_cat.spam() << "Trying to process material with semantic " << semantic << endl;
|
||||
PT_EggMaterial egg_material = new EggMaterial(semantic);
|
||||
pvector<PT_EggTexture> egg_textures;
|
||||
const FCDEffect* effect = instance->GetMaterial()->GetEffect();
|
||||
if (effect == NULL) {
|
||||
daeegg_cat.debug() << "Ignoring material (semantic: " << semantic << ") without assigned effect" << endl;
|
||||
} else {
|
||||
// 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
|
||||
<< " 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(CONV_COLOR(effect_common->GetAmbientColor()));
|
||||
////TODO: find a better way for transparency
|
||||
//LVecBase4f diffuse = CONV_COLOR(effect_common->GetDiffuseColor());
|
||||
//diffuse.set_w(diffuse.get_w() * (1.0f - effect_common->GetOpacity()));
|
||||
//egg_material->set_diff(diffuse);
|
||||
egg_material->set_diff(CONV_COLOR(effect_common->GetDiffuseColor()));
|
||||
egg_material->set_emit(CONV_COLOR(effect_common->GetEmissionColor()) * effect_common->GetEmissionFactor());
|
||||
egg_material->set_shininess(effect_common->GetShininess());
|
||||
egg_material->set_spec(CONV_COLOR(effect_common->GetSpecularColor()));
|
||||
// Now try to load in the textures
|
||||
process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::DIFFUSE, EggTexture::ET_modulate);
|
||||
process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::BUMP, EggTexture::ET_normal);
|
||||
process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::SPECULAR, EggTexture::ET_modulate_gloss);
|
||||
process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::SPECULAR_LEVEL, EggTexture::ET_gloss);
|
||||
process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::OPACITY, EggTexture::ET_unspecified, EggTexture::F_alpha);
|
||||
process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::TRANSPARENT, EggTexture::ET_unspecified, EggTexture::F_alpha);
|
||||
process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::EMISSION, EggTexture::ET_add);
|
||||
// Now, calculate the color blend stuff.
|
||||
_materials[semantic]->_blend = convert_blend(effect_common->GetTransparencyMode(),
|
||||
CONV_COLOR(effect_common->GetTranslucencyColor()),
|
||||
effect_common->GetTranslucencyFactor());
|
||||
}
|
||||
// Find an <extra> tag to support some extra stuff from extensions
|
||||
process_extra(semantic, effect->GetExtra());
|
||||
}
|
||||
daeegg_cat.spam() << "Found " << egg_textures.size() << " textures in material" << endl;
|
||||
_materials[semantic]->_egg_material = egg_material;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::process_texture_bucket
|
||||
// Access: Private
|
||||
// Description: Processes the given texture bucket and gives
|
||||
// the textures in it the given envtype and format.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DaeMaterials::
|
||||
process_texture_bucket(const string semantic, const FCDEffectStandard* effect_common, FUDaeTextureChannel::Channel bucket, EggTexture::EnvType envtype, EggTexture::Format format) {
|
||||
for (size_t tx = 0; tx < effect_common->GetTextureCount(bucket); ++tx) {
|
||||
const FCDImage* image = effect_common->GetTexture(bucket, tx)->GetImage();
|
||||
if (image == NULL) {
|
||||
daeegg_cat.warning() << "Texture references a nonexisting image!" << endl;
|
||||
} else {
|
||||
const FCDEffectParameterSampler* sampler = effect_common->GetTexture(bucket, tx)->GetSampler();
|
||||
// FCollada only supplies absolute paths. We need to grab the document
|
||||
// location ourselves and make the image path absolute.
|
||||
Filename texpath;
|
||||
if (image->GetDocument()) {
|
||||
Filename docpath = Filename::from_os_specific(FROM_FSTRING(image->GetDocument()->GetFileUrl()));
|
||||
docpath.make_canonical();
|
||||
texpath = Filename::from_os_specific(FROM_FSTRING(image->GetFilename()));
|
||||
texpath.make_canonical();
|
||||
texpath.make_relative_to(docpath.get_dirname(), true);
|
||||
daeegg_cat.debug() << "Found texture with path " << texpath << endl;
|
||||
} else {
|
||||
// Never mind.
|
||||
texpath = Filename::from_os_specific(FROM_FSTRING(image->GetFilename()));
|
||||
}
|
||||
PT_EggTexture egg_texture = new EggTexture(FROM_FSTRING(image->GetDaeId()), texpath.to_os_generic());
|
||||
// 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()]);
|
||||
}
|
||||
}
|
||||
// Apply sampler stuff
|
||||
if (sampler != NULL) {
|
||||
egg_texture->set_texture_type(convert_texture_type(sampler->GetSamplerType()));
|
||||
egg_texture->set_wrap_u(convert_wrap_mode(sampler->GetWrapS()));
|
||||
if (sampler->GetSamplerType() != FCDEffectParameterSampler::SAMPLER1D) {
|
||||
egg_texture->set_wrap_v(convert_wrap_mode(sampler->GetWrapT()));
|
||||
}
|
||||
if (sampler->GetSamplerType() == FCDEffectParameterSampler::SAMPLER3D) {
|
||||
egg_texture->set_wrap_w(convert_wrap_mode(sampler->GetWrapP()));
|
||||
}
|
||||
egg_texture->set_minfilter(convert_filter_type(sampler->GetMinFilter()));
|
||||
egg_texture->set_magfilter(convert_filter_type(sampler->GetMagFilter()));
|
||||
if (envtype != EggTexture::ET_unspecified) {
|
||||
egg_texture->set_env_type(envtype);
|
||||
}
|
||||
if (format != EggTexture::F_unspecified) {
|
||||
egg_texture->set_format(format);
|
||||
}
|
||||
}
|
||||
_materials[semantic]->_egg_textures.push_back(egg_texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::process_extra
|
||||
// Access: Private
|
||||
// Description: Processes the extra data in the given <extra> tag.
|
||||
// If the given element is NULL, it just silently
|
||||
// returns.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DaeMaterials::
|
||||
process_extra(const string semantic, const FCDExtra* extra) {
|
||||
if (extra == NULL) return;
|
||||
const FCDEType* etype = extra->GetDefaultType();
|
||||
if (etype == NULL) return;
|
||||
for (size_t et = 0; et < etype->GetTechniqueCount(); ++et) {
|
||||
const FCDENode* enode = ((const FCDENode*)(etype->GetTechnique(et)))->FindChildNode("double_sided");
|
||||
if (enode != NULL) {
|
||||
if (trim(enode->GetContent()) == "1") {
|
||||
_materials[semantic]->_double_sided = true;
|
||||
} else if (trim(enode->GetContent()) == "0") {
|
||||
_materials[semantic]->_double_sided = false;
|
||||
} else {
|
||||
daeegg_cat.warning() << "Expected <double_sided> tag to be either 1 or 0, found '" << enode->GetContent() << "' instead" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::apply_to
|
||||
// Access: Public
|
||||
// Description: Applies the stuff to the given EggPrimitive.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DaeMaterials::
|
||||
apply_to(const string semantic, const PT(EggPrimitive) to) {
|
||||
if (_materials.count(semantic) > 0) {
|
||||
to->set_material(_materials[semantic]->_egg_material);
|
||||
for (pvector<PT_EggTexture>::iterator it = _materials[semantic]->_egg_textures.begin(); it != _materials[semantic]->_egg_textures.end(); ++it) {
|
||||
daeegg_cat.spam() << "Applying texture " << (*it)->get_name() << " from material with semantic " << semantic << endl;
|
||||
to->add_texture(*it);
|
||||
}
|
||||
to->set_bface_flag(_materials[semantic]->_double_sided);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::apply_to
|
||||
// Access: Public
|
||||
// Description: Applies the colorblend stuff to the given EggGroup.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DaeMaterials::
|
||||
apply_to(const string semantic, const PT(EggGroup) to) {
|
||||
if (_materials.count(semantic) > 0) {
|
||||
PT(DaeBlendSettings) blend = _materials[semantic]->_blend;
|
||||
if (blend->_enabled) {
|
||||
to->set_blend_mode(EggGroup::BM_add);
|
||||
to->set_blend_color(blend->_color);
|
||||
to->set_blend_operand_a(blend->_operand_a);
|
||||
to->set_blend_operand_b(blend->_operand_b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::convert_texture_type
|
||||
// Access: Public, Static
|
||||
// Description: Converts an FCollada sampler type to the EggTexture
|
||||
// texture type equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggTexture::TextureType DaeMaterials::
|
||||
convert_texture_type(const FCDEffectParameterSampler::SamplerType orig_type) {
|
||||
switch (orig_type) {
|
||||
case FCDEffectParameterSampler::SAMPLER1D:
|
||||
return EggTexture::TT_1d_texture;
|
||||
case FCDEffectParameterSampler::SAMPLER2D:
|
||||
return EggTexture::TT_2d_texture;
|
||||
case FCDEffectParameterSampler::SAMPLER3D:
|
||||
return EggTexture::TT_3d_texture;
|
||||
case FCDEffectParameterSampler::SAMPLERCUBE:
|
||||
return EggTexture::TT_cube_map;
|
||||
default:
|
||||
daeegg_cat.warning() << "Invalid sampler type found" << endl;
|
||||
}
|
||||
return EggTexture::TT_unspecified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::convert_wrap_mode
|
||||
// Access: Public, Static
|
||||
// Description: Converts an FCollada wrap mode to the
|
||||
// EggTexture wrap mode equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggTexture::WrapMode DaeMaterials::
|
||||
convert_wrap_mode(const FUDaeTextureWrapMode::WrapMode orig_mode) {
|
||||
switch (orig_mode) {
|
||||
case FUDaeTextureWrapMode::NONE:
|
||||
//FIXME: this shouldnt be unspecified
|
||||
return EggTexture::WM_unspecified;
|
||||
case FUDaeTextureWrapMode::WRAP:
|
||||
return EggTexture::WM_repeat;
|
||||
case FUDaeTextureWrapMode::MIRROR:
|
||||
return EggTexture::WM_mirror;
|
||||
case FUDaeTextureWrapMode::CLAMP:
|
||||
return EggTexture::WM_clamp;
|
||||
case FUDaeTextureWrapMode::BORDER:
|
||||
return EggTexture::WM_border_color;
|
||||
case FUDaeTextureWrapMode::UNKNOWN:
|
||||
return EggTexture::WM_unspecified;
|
||||
default:
|
||||
daeegg_cat.warning() << "Invalid wrap mode found: " << FUDaeTextureWrapMode::ToString(orig_mode) << endl;
|
||||
}
|
||||
return EggTexture::WM_unspecified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::convert_filter_type
|
||||
// Access: Public, Static
|
||||
// Description: Converts an FCollada filter function to the
|
||||
// EggTexture wrap type equivalent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggTexture::FilterType DaeMaterials::
|
||||
convert_filter_type(const FUDaeTextureFilterFunction::FilterFunction orig_type) {
|
||||
switch (orig_type) {
|
||||
case FUDaeTextureFilterFunction::NONE:
|
||||
//FIXME: this shouldnt be unspecified
|
||||
return EggTexture::FT_unspecified;
|
||||
case FUDaeTextureFilterFunction::NEAREST:
|
||||
return EggTexture::FT_nearest;
|
||||
case FUDaeTextureFilterFunction::LINEAR:
|
||||
return EggTexture::FT_linear;
|
||||
case FUDaeTextureFilterFunction::NEAREST_MIPMAP_NEAREST:
|
||||
return EggTexture::FT_nearest_mipmap_nearest;
|
||||
case FUDaeTextureFilterFunction::LINEAR_MIPMAP_NEAREST:
|
||||
return EggTexture::FT_linear_mipmap_nearest;
|
||||
case FUDaeTextureFilterFunction::NEAREST_MIPMAP_LINEAR:
|
||||
return EggTexture::FT_nearest_mipmap_linear;
|
||||
case FUDaeTextureFilterFunction::LINEAR_MIPMAP_LINEAR:
|
||||
return EggTexture::FT_linear_mipmap_linear;
|
||||
case FUDaeTextureFilterFunction::UNKNOWN:
|
||||
return EggTexture::FT_unspecified;
|
||||
default:
|
||||
daeegg_cat.warning() << "Unknown filter type found: " << FUDaeTextureFilterFunction::ToString(orig_type) << endl;
|
||||
}
|
||||
return EggTexture::FT_unspecified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DaeMaterials::convert_blend
|
||||
// Access: Private, Static
|
||||
// Description: Converts collada blend attribs to Panda's equivalents.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(DaeMaterials::DaeBlendSettings) DaeMaterials::
|
||||
convert_blend(FCDEffectStandard::TransparencyMode mode, Colorf transparent, double transparency) {
|
||||
// Create the DaeBlendSettings and fill it with some defaults.
|
||||
PT(DaeBlendSettings) blend = new DaeBlendSettings();
|
||||
blend->_enabled = true;
|
||||
blend->_color = Colorf::zero();
|
||||
blend->_operand_a = EggGroup::BO_unspecified;
|
||||
blend->_operand_b = EggGroup::BO_unspecified;
|
||||
|
||||
// First fill in the color value.
|
||||
if (mode == FCDEffectStandard::A_ONE) {// || mode == FCDEffectStandard::A_ZERO) {
|
||||
double value = transparent[3] * transparency;
|
||||
blend->_color = Colorf(value, value, value, value);
|
||||
} else if (mode == FCDEffectStandard::RGB_ZERO) {//|| mode == FCDEffectStandard::RGB_ONE) {
|
||||
blend->_color = transparent * transparency;
|
||||
blend->_color[3] = luminance(blend->_color);
|
||||
} else {
|
||||
daeegg_cat.error() << "Unknown opaque type found!" << endl;
|
||||
blend->_enabled = false;
|
||||
return blend;
|
||||
}
|
||||
|
||||
// Now figure out the operands.
|
||||
if (mode == FCDEffectStandard::RGB_ZERO) {// || mode == FCDEffectStandard::A_ZERO) {
|
||||
blend->_operand_a = EggGroup::BO_constant_color;
|
||||
blend->_operand_b = EggGroup::BO_one_minus_constant_color;
|
||||
} else if (mode == FCDEffectStandard::A_ONE) {// || mode == FCDEffectStandard::RGB_ONE) {
|
||||
blend->_operand_a = EggGroup::BO_one_minus_constant_color;
|
||||
blend->_operand_b = EggGroup::BO_constant_color;
|
||||
} else {
|
||||
daeegg_cat.error() << "Unknown opaque type found!" << endl;
|
||||
blend->_enabled = false;
|
||||
return blend;
|
||||
}
|
||||
|
||||
// See if we can optimize out the color.
|
||||
if (blend->_operand_a == EggGroup::BO_constant_color) {
|
||||
if (blend->_color[0] == blend->_color[1] == blend->_color[2] == blend->_color[3] == 0) {
|
||||
blend->_operand_a = EggGroup::BO_zero;
|
||||
}
|
||||
if (blend->_color[0] == blend->_color[1] == blend->_color[2] == blend->_color[3] == 1) {
|
||||
blend->_operand_a = EggGroup::BO_one;
|
||||
}
|
||||
}
|
||||
if (blend->_operand_b == EggGroup::BO_one_minus_constant_color) {
|
||||
if (blend->_color[0] == blend->_color[1] == blend->_color[2] == blend->_color[3] == 0) {
|
||||
blend->_operand_b = EggGroup::BO_one;
|
||||
}
|
||||
if (blend->_color[0] == blend->_color[1] == blend->_color[2] == blend->_color[3] == 1) {
|
||||
blend->_operand_b = EggGroup::BO_zero;
|
||||
}
|
||||
}
|
||||
|
||||
// See if we can entirely disable the blend.
|
||||
if (blend->_operand_a == EggGroup::BO_one && blend->_operand_b == EggGroup::BO_zero) {
|
||||
blend->_enabled = false;
|
||||
}
|
||||
return blend;
|
||||
}
|
97
pandatool/src/daeegg/daeMaterials.h
Executable file
97
pandatool/src/daeegg/daeMaterials.h
Executable file
@ -0,0 +1,97 @@
|
||||
// Filename: daeMaterials.h
|
||||
// Created by: pro-rsoft (03Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DAEMATERIALS_H
|
||||
#define DAEMATERIALS_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "eggMaterial.h"
|
||||
#include "eggTexture.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "eggGroup.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pt_EggTexture.h"
|
||||
#include "pt_EggMaterial.h"
|
||||
|
||||
#include "pre_fcollada_include.h"
|
||||
#include "FCollada.h"
|
||||
#include "FCDocument/FCDGeometryInstance.h"
|
||||
#include "FCDocument/FCDMaterialInstance.h"
|
||||
#include "FCDocument/FCDEffectStandard.h"
|
||||
#include "FCDocument/FCDEffectParameterSampler.h"
|
||||
#include "FCDocument/FCDExtra.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DaeMaterials
|
||||
// Description : This class is seperated from the converter file
|
||||
// because otherwise it would get too big and
|
||||
// needlessly complicated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class DaeMaterials : public TypedReferenceCount {
|
||||
public:
|
||||
DaeMaterials(const FCDGeometryInstance* geometry_instance);
|
||||
virtual ~DaeMaterials() {};
|
||||
|
||||
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);
|
||||
|
||||
static EggTexture::TextureType convert_texture_type(const FCDEffectParameterSampler::SamplerType orig_type);
|
||||
static EggTexture::WrapMode convert_wrap_mode(const FUDaeTextureWrapMode::WrapMode orig_mode);
|
||||
static EggTexture::FilterType convert_filter_type(const FUDaeTextureFilterFunction::FilterFunction orig_type);
|
||||
|
||||
private:
|
||||
// Holds stuff for color blend attribs.
|
||||
struct DaeBlendSettings : public ReferenceCount {
|
||||
bool _enabled;
|
||||
Colorf _color;
|
||||
EggGroup::BlendOperand _operand_a;
|
||||
EggGroup::BlendOperand _operand_b;
|
||||
};
|
||||
|
||||
// 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;
|
||||
PT(DaeBlendSettings) _blend;
|
||||
};
|
||||
|
||||
void process_texture_bucket(const string semantic, const FCDEffectStandard* effect_common, FUDaeTextureChannel::Channel bucket, EggTexture::EnvType envtype = EggTexture::ET_unspecified, EggTexture::Format format = EggTexture::F_unspecified);
|
||||
void process_extra(const string semantic, const FCDExtra* extra);
|
||||
static PT(DaeBlendSettings) convert_blend(FCDEffectStandard::TransparencyMode mode, Colorf transparent, double transparency);
|
||||
|
||||
pmap<const string, PT(DaeMaterial)> _materials;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "DaeMaterials",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#endif
|
614
pandatool/src/daeegg/daeToEggConverter.cxx
Executable file
614
pandatool/src/daeegg/daeToEggConverter.cxx
Executable file
@ -0,0 +1,614 @@
|
||||
// Filename: daeToEggConverter.cxx
|
||||
// Created by: pro-rsoft (08May08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "daeToEggConverter.h"
|
||||
#include "config_daeegg.h"
|
||||
#include "daeCharacter.h"
|
||||
#include "dcast.h"
|
||||
#include "string_utils.h"
|
||||
#include "eggData.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "eggLine.h"
|
||||
#include "eggPolygon.h"
|
||||
#include "eggTriangleFan.h"
|
||||
#include "eggTriangleStrip.h"
|
||||
#include "eggPoint.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
#include "eggSAnimData.h"
|
||||
#include "pt_EggVertex.h"
|
||||
|
||||
#include "FCDocument/FCDAsset.h"
|
||||
#include "FCDocument/FCDocumentTools.h"
|
||||
#include "FCDocument/FCDSceneNode.h"
|
||||
#include "FCDocument/FCDSceneNodeTools.h"
|
||||
#include "FCDocument/FCDGeometry.h"
|
||||
#include "FCDocument/FCDGeometryInstance.h"
|
||||
#include "FCDocument/FCDGeometryPolygons.h"
|
||||
#include "FCDocument/FCDGeometrySource.h"
|
||||
#include "FCDocument/FCDSkinController.h"
|
||||
#include "FCDocument/FCDController.h"
|
||||
#include "FCDocument/FCDControllerInstance.h"
|
||||
#include "FCDocument/FCDMorphController.h"
|
||||
#include "FCDocument/FCDMaterialInstance.h"
|
||||
#include "FCDocument/FCDExtra.h"
|
||||
#include "FCDocument/FCDEffect.h"
|
||||
#include "FCDocument/FCDEffectStandard.h"
|
||||
|
||||
// Useful conversion stuff
|
||||
#define TO_VEC3(v) (LVecBase3d(v[0], v[1], v[2]))
|
||||
#define TO_VEC4(v) (LVecBase4d(v[0], v[1], v[2], v[3]))
|
||||
#define TO_COLOR(v) (Colorf(v[0], v[1], v[2], v[3]))
|
||||
#define FROM_VEC3(v) (FMVector3(v[0], v[1], v[2]))
|
||||
#define FROM_VEC4(v) (FMVector4(v[0], v[1], v[2], v[3]))
|
||||
#define FROM_MAT4(v) (FMMatrix44(v.getData()))
|
||||
#define FROM_FSTRING(fs) (string(fs.c_str()))
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEggConverter::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DAEToEggConverter::
|
||||
DAEToEggConverter() {
|
||||
_document = NULL;
|
||||
_table = NULL;
|
||||
_frame_rate = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEggConverter::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DAEToEggConverter::
|
||||
DAEToEggConverter(const DAEToEggConverter ©) :
|
||||
SomethingToEggConverter(copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEggConverter::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DAEToEggConverter::
|
||||
~DAEToEggConverter() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEggConverter::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new copy of the converter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SomethingToEggConverter *DAEToEggConverter::
|
||||
make_copy() {
|
||||
return new DAEToEggConverter(*this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEggConverter::get_name
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the English name of the file type this
|
||||
// converter supports.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string DAEToEggConverter::
|
||||
get_name() const {
|
||||
return "COLLADA";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEggConverter::get_extension
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the common extension of the file type this
|
||||
// converter supports.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string DAEToEggConverter::
|
||||
get_extension() const {
|
||||
return "dae";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEggConverter::convert_file
|
||||
// Access: Public, Virtual
|
||||
// Description: Handles the reading of the input file and converting
|
||||
// it to egg. Returns true if successful, false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DAEToEggConverter::
|
||||
convert_file(const Filename &filename) {
|
||||
// Reset stuff
|
||||
clear_error();
|
||||
_joints.clear();
|
||||
_vertex_pools.clear();
|
||||
_skeletons.clear();
|
||||
_frame_rate = -1;
|
||||
|
||||
// The default coordinate system is Y-up
|
||||
if (_egg_data->get_coordinate_system() == CS_default) {
|
||||
_egg_data->set_coordinate_system(CS_yup_right);
|
||||
}
|
||||
|
||||
// Read the file
|
||||
FCollada::Initialize();
|
||||
_document = FCollada::LoadDocument(filename.to_os_specific().c_str());
|
||||
if(_document == NULL) {
|
||||
daeegg_cat.error() << "Failed to load document: " << _error_handler.GetErrorString() << endl;
|
||||
FCollada::Release();
|
||||
return false;
|
||||
}
|
||||
// Make sure the file uses consistent coordinate system and length
|
||||
FCDocumentTools::StandardizeUpAxisAndLength(_document);
|
||||
|
||||
_table = new EggTable();
|
||||
_table->set_table_type(EggTable::TT_table);
|
||||
// Process the stuff
|
||||
process_asset();
|
||||
preprocess();
|
||||
FCDSceneNode* visual_scene = _document->GetVisualSceneInstance();
|
||||
if (visual_scene != NULL) {
|
||||
// First check for an <extra> tag
|
||||
const FCDExtra* extra = visual_scene->GetExtra();
|
||||
//FIXME: eek this looks horrid
|
||||
if (extra != NULL) {
|
||||
const FCDEType* etype = extra->GetDefaultType();
|
||||
if (etype != NULL) {
|
||||
const FCDENode* enode = (const FCDENode*) etype->FindTechnique("MAX3D");
|
||||
if (enode != NULL) {
|
||||
enode = enode->FindChildNode("frame_rate");
|
||||
if (enode != NULL && !string_to_int(enode->GetContent(), _frame_rate)) {
|
||||
daeegg_cat.warning() << "Invalid integer in <frame_rate> tag: '" << enode->GetContent() << "'" << endl;
|
||||
} } } }
|
||||
// Now loop through the children
|
||||
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
|
||||
process_node(DCAST(EggGroupNode, _egg_data), visual_scene->GetChild(ch));
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(visual_scene);
|
||||
|
||||
_egg_data->add_child(_table);
|
||||
|
||||
// Clean up and return
|
||||
SAFE_DELETE(_document);
|
||||
FCollada::Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DAEToEggConverter::process_asset() {
|
||||
if (_document->GetAsset() == NULL) return;
|
||||
// Read out the coordinate system
|
||||
FMVector3 up_axis (_document->GetAsset()->GetUpAxis());
|
||||
if (up_axis == FMVector3(0, 1, 0)) {
|
||||
_egg_data->set_coordinate_system(CS_yup_right);
|
||||
} else if (up_axis == FMVector3(0, 0, 1)) {
|
||||
_egg_data->set_coordinate_system(CS_zup_right);
|
||||
} else {
|
||||
_egg_data->set_coordinate_system(CS_invalid);
|
||||
daeegg_cat.warning() << "Unrecognized coordinate system!\n";
|
||||
}
|
||||
}
|
||||
|
||||
// This function lists all the joints and referenced skeletons
|
||||
void DAEToEggConverter::preprocess(const FCDSceneNode* node) {
|
||||
// If the node is NULL, take the visual scene instance.
|
||||
if (node == NULL) {
|
||||
assert(_document != NULL);
|
||||
_skeletons.clear();
|
||||
_joints.clear();
|
||||
node = _document->GetVisualSceneInstance();
|
||||
}
|
||||
if (node == NULL) return;
|
||||
if (node->IsJoint()) {
|
||||
_joints[FROM_FSTRING(node->GetDaeId())] = NULL;
|
||||
}
|
||||
// Loop through the instances first.
|
||||
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
||||
if (node->GetInstance(in)->GetType() == FCDEntityInstance::CONTROLLER) {
|
||||
// Loop through the skeleton roots now.
|
||||
FCDSceneNodeList roots = ((FCDControllerInstance*) node->GetInstance(in))->FindSkeletonNodes();
|
||||
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
|
||||
daeegg_cat.spam() << "Found referenced skeleton root " << FROM_FSTRING((*it)->GetDaeId()) << endl;
|
||||
_skeletons.push_back(FROM_FSTRING((*it)->GetDaeId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now loop through the children and recurse.
|
||||
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
||||
preprocess(node->GetChild(ch));
|
||||
}
|
||||
}
|
||||
|
||||
// Process the node. If forced is true, it will even process it if its known to be a skeleton root.
|
||||
void DAEToEggConverter::process_node(PT(EggGroupNode) parent, const FCDSceneNode* node, bool forced) {
|
||||
nassertv(node != NULL);
|
||||
string node_id = FROM_FSTRING(node->GetDaeId());
|
||||
daeegg_cat.spam() << "Processing node with ID '" << node_id << "'" << endl;
|
||||
// Important! If it's known to be a skeleton root, ignore it for now, unless we're processing forced.
|
||||
if (!forced && count(_skeletons.begin(), _skeletons.end(), node_id) > 0) {
|
||||
daeegg_cat.spam() << "Ignoring skeleton root node with ID '" << node_id << "', we'll process it later" << endl;
|
||||
return;
|
||||
}
|
||||
// Create an egg group for this node
|
||||
PT(EggGroup) node_group = new EggGroup(node_id);
|
||||
parent->add_child(node_group);
|
||||
// Check if its a joint
|
||||
if (node->IsJoint()) {
|
||||
node_group->set_group_type(EggGroup::GT_joint);
|
||||
_joints[node_id] = node_group;
|
||||
}
|
||||
// Loop through the transforms and apply them
|
||||
for (size_t tr = 0; tr < node->GetTransformCount(); ++tr) {
|
||||
apply_transform(node_group, node->GetTransform(tr));
|
||||
}
|
||||
// Loop through the instances and process them
|
||||
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
||||
process_instance(node_group, node->GetInstance(in));
|
||||
}
|
||||
// Loop through the children and recursively process them
|
||||
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
||||
process_node(DCAST(EggGroupNode, node_group), node->GetChild(ch));
|
||||
}
|
||||
// Loop through any possible scene node instances and process those, too.
|
||||
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
||||
if (node->GetInstance(in)->GetEntity() && node->GetInstance(in)->GetEntity()->GetType() == FCDEntity::SCENE_NODE) {
|
||||
process_node(DCAST(EggGroupNode, node_group), (const FCDSceneNode*) node->GetInstance(in)->GetEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DAEToEggConverter::process_instance(PT(EggGroup) parent, const FCDEntityInstance* instance) {
|
||||
nassertv(instance != NULL);
|
||||
nassertv(instance->GetEntity() != NULL);
|
||||
// Check what kind of instance this is
|
||||
switch (instance->GetType()) {
|
||||
case FCDEntityInstance::GEOMETRY: {
|
||||
const FCDGeometry* geometry = (const FCDGeometry*) instance->GetEntity();
|
||||
assert(geometry != NULL);
|
||||
if (geometry->IsMesh()) {
|
||||
// Now, handle the mesh.
|
||||
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
|
||||
}
|
||||
if (geometry->IsSpline()) {
|
||||
process_spline(parent, FROM_FSTRING(geometry->GetDaeId()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
|
||||
}
|
||||
break; }
|
||||
case FCDEntityInstance::CONTROLLER: {
|
||||
// Add the dart tag and process the controller instance
|
||||
parent->set_dart_type(EggGroup::DT_default);
|
||||
process_controller(parent, (const FCDControllerInstance*) instance);
|
||||
break; }
|
||||
case FCDEntityInstance::MATERIAL:
|
||||
// We don't process this directly, handled per-geometry instead.
|
||||
break;
|
||||
case FCDEntityInstance::SIMPLE: {
|
||||
// Grab the entity and check it's type.
|
||||
const FCDEntity* entity = instance->GetEntity();
|
||||
if (entity->GetType() != FCDEntity::SCENE_NODE) {
|
||||
daeegg_cat.warning() << "Unsupported entity type found" << endl;
|
||||
}
|
||||
break; }
|
||||
default:
|
||||
daeegg_cat.warning() << "Unsupported instance type found" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Processes the given mesh.
|
||||
void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* mesh, PT(DaeMaterials) materials) {
|
||||
nassertv(mesh != NULL);
|
||||
// Create the egg stuff to hold this mesh
|
||||
PT(EggGroup) mesh_group = new EggGroup(FROM_FSTRING(mesh->GetDaeId()));
|
||||
parent->add_child(mesh_group);
|
||||
PT(EggVertexPool) mesh_pool = new EggVertexPool(FROM_FSTRING(mesh->GetDaeId()));
|
||||
mesh_group->add_child(mesh_pool);
|
||||
_vertex_pools[FROM_FSTRING(mesh->GetDaeId())] = mesh_pool;
|
||||
// First retrieve the vertex source
|
||||
if (mesh->GetSourceCount() == 0) return;
|
||||
const FCDGeometrySource* vsource = mesh->FindSourceByType(FUDaeGeometryInput::POSITION);
|
||||
if (vsource == NULL) return;
|
||||
// Stores which group holds the primitives.
|
||||
PT(EggGroup) primitiveholder;
|
||||
// Loop through the polygon groups and add them
|
||||
for (size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) {
|
||||
const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr);
|
||||
primitiveholder = mesh_group;
|
||||
// If we have materials, make a group for each material. Then, apply the material's per-group stuff.
|
||||
if (materials != NULL && (!polygons->GetMaterialSemantic().empty()) && mesh->GetPolygonsCount() > 1) {
|
||||
primitiveholder = new EggGroup(FROM_FSTRING(mesh->GetDaeId()) + FROM_FSTRING(polygons->GetMaterialSemantic()));
|
||||
mesh_group->add_child(primitiveholder);
|
||||
}
|
||||
// Apply the per-group data of the materials, if we have it.
|
||||
if (materials != NULL) {
|
||||
materials->apply_to(FROM_FSTRING(polygons->GetMaterialSemantic()), primitiveholder);
|
||||
}
|
||||
// Find the position sources
|
||||
const FCDGeometryPolygonsInput* pinput = polygons->FindInput(FUDaeGeometryInput::POSITION);
|
||||
assert(pinput != NULL);
|
||||
const uint32* indices = pinput->GetIndices();
|
||||
// Find the normal sources
|
||||
const FCDGeometrySource* nsource = mesh->FindSourceByType(FUDaeGeometryInput::NORMAL);
|
||||
const FCDGeometryPolygonsInput* ninput = polygons->FindInput(FUDaeGeometryInput::NORMAL);
|
||||
const uint32* nindices;
|
||||
if (ninput != NULL) nindices = ninput->GetIndices();
|
||||
// Find texcoord sources
|
||||
const FCDGeometrySource* tcsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXCOORD);
|
||||
const FCDGeometryPolygonsInput* tcinput = polygons->FindInput(FUDaeGeometryInput::TEXCOORD);
|
||||
const uint32* tcindices;
|
||||
if (tcinput != NULL) tcindices = tcinput->GetIndices();
|
||||
// Find vcolor sources
|
||||
const FCDGeometrySource* csource = mesh->FindSourceByType(FUDaeGeometryInput::COLOR);
|
||||
const FCDGeometryPolygonsInput* cinput = polygons->FindInput(FUDaeGeometryInput::COLOR);
|
||||
const uint32* cindices;
|
||||
if (cinput != NULL) cindices = cinput->GetIndices();
|
||||
// Find binormal sources
|
||||
const FCDGeometrySource* bsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXBINORMAL);
|
||||
const FCDGeometryPolygonsInput* binput = polygons->FindInput(FUDaeGeometryInput::TEXBINORMAL);
|
||||
const uint32* bindices;
|
||||
if (binput != NULL) bindices = binput->GetIndices();
|
||||
// Find tangent sources
|
||||
const FCDGeometrySource* tsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXTANGENT);
|
||||
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 ("");
|
||||
if (materials != NULL && tcinput != NULL) {
|
||||
uvsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), tcinput->GetSet());
|
||||
}
|
||||
// Loop through the indices and add the vertices.
|
||||
for (size_t ix = 0; ix < pinput->GetIndexCount(); ++ix) {
|
||||
PT_EggVertex vertex = mesh_pool->make_new_vertex();
|
||||
const float* data = &vsource->GetData()[indices[ix]*3];
|
||||
vertex->set_pos(LPoint3d(data[0], data[1], data[2]));
|
||||
// Process the normal
|
||||
if (nsource != NULL && ninput != NULL) {
|
||||
assert(nsource->GetStride() == 3);
|
||||
data = &nsource->GetData()[nindices[ix]*3];
|
||||
vertex->set_normal(LVecBase3d(data[0], data[1], data[2]));
|
||||
}
|
||||
// Process the texcoords
|
||||
if (tcsource != NULL && tcinput != NULL) {
|
||||
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]));
|
||||
} else {
|
||||
vertex->set_uvw(uvsetname, LPoint3d(data[0], data[1], data[2]));
|
||||
}
|
||||
}
|
||||
// Process the color
|
||||
if (csource != NULL && cinput != NULL) {
|
||||
assert(csource->GetStride() == 4);
|
||||
data = &csource->GetData()[cindices[ix]*4];
|
||||
vertex->set_color(Colorf(data[0], data[1], data[2], data[3]));
|
||||
}
|
||||
// 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]));
|
||||
}
|
||||
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]));
|
||||
}
|
||||
}
|
||||
vertex->transform(parent->get_node_to_vertex());
|
||||
}
|
||||
// Now loop through the faces
|
||||
for (size_t fa = polygons->GetFaceOffset(); fa < polygons->GetFaceOffset() + polygons->GetFaceCount(); ++fa) {
|
||||
PT(EggPrimitive) primitive = NULL;
|
||||
// Create a primitive that matches the fcollada type
|
||||
switch (polygons->GetPrimitiveType()) {
|
||||
case FCDGeometryPolygons::LINES:
|
||||
primitive = new EggLine();
|
||||
break;
|
||||
case FCDGeometryPolygons::POLYGONS:
|
||||
primitive = new EggPolygon();
|
||||
break;
|
||||
case FCDGeometryPolygons::TRIANGLE_FANS:
|
||||
primitive = new EggTriangleFan();
|
||||
break;
|
||||
case FCDGeometryPolygons::TRIANGLE_STRIPS:
|
||||
primitive = new EggTriangleStrip();
|
||||
break;
|
||||
case FCDGeometryPolygons::POINTS:
|
||||
primitive = new EggPoint();
|
||||
break;
|
||||
case FCDGeometryPolygons::LINE_STRIPS:
|
||||
daeegg_cat.warning() << "Linestrips not yet supported!" << endl;
|
||||
break;
|
||||
default:
|
||||
daeegg_cat.warning() << "Unsupported primitive type found!\n";
|
||||
}
|
||||
if (primitive != NULL) {
|
||||
primitiveholder->add_child(primitive);
|
||||
if (materials != NULL) {
|
||||
materials->apply_to(FROM_FSTRING(polygons->GetMaterialSemantic()), primitive);
|
||||
}
|
||||
for (size_t ve = polygons->GetFaceVertexOffset(fa); ve < polygons->GetFaceVertexOffset(fa) + polygons->GetFaceVertexCount(fa); ++ve) {
|
||||
assert(mesh_pool->has_vertex(ve));
|
||||
primitive->add_vertex(mesh_pool->get_vertex(ve));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DAEToEggConverter::process_spline(PT(EggGroup) parent, const string group_name, FCDGeometrySpline* geometry_spline) {
|
||||
assert(geometry_spline != NULL);
|
||||
PT(EggGroup) result = new EggGroup(group_name);
|
||||
parent->add_child(result);
|
||||
//TODO: if its not a nurbs, make it convert between the types
|
||||
if (geometry_spline->GetType() != FUDaeSplineType::NURBS) {
|
||||
daeegg_cat.warning() << "Only NURBS curves are supported (yet)!" << endl;
|
||||
} else {
|
||||
// Loop through the splines
|
||||
for (size_t sp = 0; sp < geometry_spline->GetSplineCount(); ++sp) {
|
||||
process_spline(result, geometry_spline->GetSpline(sp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DAEToEggConverter::process_spline(PT(EggGroup) parent, const FCDSpline* spline) {
|
||||
assert(spline != NULL);
|
||||
nassertv(spline->GetSplineType() == FUDaeSplineType::NURBS);
|
||||
// Now load in the nurbs curve to the egg library
|
||||
PT(EggNurbsCurve) nurbs_curve = new EggNurbsCurve(FROM_FSTRING(spline->GetName()));
|
||||
parent->add_child(nurbs_curve);
|
||||
//TODO: what value is this?
|
||||
nurbs_curve->setup(0, ((const FCDNURBSSpline*) spline)->GetKnotCount());
|
||||
for (size_t kn = 0; kn < ((const FCDNURBSSpline*) spline)->GetKnotCount(); ++kn) {
|
||||
const float* knot = ((const FCDNURBSSpline*) spline)->GetKnot(kn);
|
||||
assert(knot != NULL);
|
||||
nurbs_curve->set_knot(kn, *knot);
|
||||
}
|
||||
for (size_t cv = 0; cv < spline->GetCVCount(); ++cv) {
|
||||
PT_EggVertex c_vtx = new EggVertex();
|
||||
c_vtx->set_pos(TO_VEC3(*spline->GetCV(cv)));
|
||||
c_vtx->transform(parent->get_node_to_vertex());
|
||||
nurbs_curve->add_vertex(c_vtx);
|
||||
}
|
||||
}
|
||||
|
||||
void DAEToEggConverter::process_controller(PT(EggGroup) parent, const FCDControllerInstance* instance) {
|
||||
assert(instance != NULL);
|
||||
const FCDController* controller = (const FCDController*) instance->GetEntity();
|
||||
assert(controller != NULL);
|
||||
PT(EggVertexPool) vertex_pool = NULL;
|
||||
// Add the skin geometry
|
||||
const FCDGeometry* geometry = controller->GetBaseGeometry();
|
||||
if (geometry != NULL) {
|
||||
if (geometry->IsMesh()) {
|
||||
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
|
||||
if (_vertex_pools.count(FROM_FSTRING(geometry->GetMesh()->GetDaeId()))) {
|
||||
vertex_pool = _vertex_pools[FROM_FSTRING(geometry->GetMesh()->GetDaeId())];
|
||||
}
|
||||
}
|
||||
if (geometry->IsSpline()) {
|
||||
process_spline(parent, FROM_FSTRING(geometry->GetDaeId()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
|
||||
}
|
||||
}
|
||||
// Add the joint hierarchy
|
||||
FCDSceneNodeList roots = (const_cast<FCDControllerInstance*> (instance))->FindSkeletonNodes();
|
||||
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
|
||||
process_node(DCAST(EggGroupNode, parent), *it, true);
|
||||
}
|
||||
if (controller->IsSkin()) {
|
||||
// Load in the vertex influences first
|
||||
pmap<int32, pvector<pair<PT_EggVertex, float> > > influences;
|
||||
if (vertex_pool) {
|
||||
for (size_t in = 0; in < controller->GetSkinController()->GetInfluenceCount(); ++in) {
|
||||
assert(vertex_pool->has_vertex(in));
|
||||
for (size_t pa = 0; pa < controller->GetSkinController()->GetVertexInfluence(in)->GetPairCount(); ++pa) {
|
||||
const FCDJointWeightPair* jwpair = controller->GetSkinController()->GetVertexInfluence(in)->GetPair(pa);
|
||||
influences[jwpair->jointIndex].push_back(pair<PT_EggVertex, float> (vertex_pool->get_vertex(in), jwpair->weight));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Loop through the joints in the vertex influences
|
||||
for (pmap<int32, pvector<pair<PT_EggVertex, float> > >::iterator it = influences.begin(); it != influences.end(); ++it) {
|
||||
if (it->first == -1) {
|
||||
daeegg_cat.warning() << "Ignoring vertex influence with negative joint index\n";
|
||||
//FIXME: Why are there joints with index -1
|
||||
} else {
|
||||
const string joint_id = FROM_FSTRING(controller->GetSkinController()->GetJoint(it->first)->GetId());
|
||||
//TODO: what if the joints have just not been defined yet?
|
||||
if (_joints.count(joint_id) > 0) {
|
||||
if (_joints[joint_id]) {
|
||||
for (pvector<pair<PT_EggVertex, float> >::iterator vi = it->second.begin(); vi != it->second.end(); ++vi) {
|
||||
_joints[joint_id]->ref_vertex(vi->first, vi->second);
|
||||
}
|
||||
} else {
|
||||
daeegg_cat.warning() << "Unprocessed joint being referenced: '" << joint_id << "'" << endl;
|
||||
}
|
||||
} else {
|
||||
daeegg_cat.warning() << "Unknown joint being referenced: '" << joint_id << "'" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller->IsMorph()) {
|
||||
assert(controller != NULL);
|
||||
const FCDMorphController* morph_controller = controller->GetMorphController();
|
||||
assert(morph_controller != NULL);
|
||||
PT(EggTable) bundle = new EggTable(parent->get_name());
|
||||
bundle->set_table_type(EggTable::TT_bundle);
|
||||
PT(EggTable) morph = new EggTable("morph");
|
||||
morph->set_table_type(EggTable::TT_table);
|
||||
bundle->add_child(morph);
|
||||
// Loop through the morph targets.
|
||||
for (size_t mt = 0; mt < morph_controller->GetTargetCount(); ++mt) {
|
||||
const FCDMorphTarget* morph_target = morph_controller->GetTarget(mt);
|
||||
assert(morph_target != NULL);
|
||||
PT(EggSAnimData) target = new EggSAnimData(FROM_FSTRING(morph_target->GetGeometry()->GetDaeId()));
|
||||
if (morph_target->IsAnimated()) {
|
||||
//TODO
|
||||
} else {
|
||||
target->add_data(morph_target->GetWeight());
|
||||
}
|
||||
morph->add_child(target);
|
||||
}
|
||||
}
|
||||
|
||||
// Get a <Bundle> for the character and add it to the table
|
||||
PT(DaeCharacter) character = new DaeCharacter(parent->get_name(), instance);
|
||||
_table->add_child(character->as_egg_bundle());
|
||||
}
|
||||
|
||||
LMatrix4d DAEToEggConverter::convert_matrix(const FMMatrix44& matrix) {
|
||||
LMatrix4d result = LMatrix4d::zeros_mat();
|
||||
for (char x = 0; x < 4; ++x) {
|
||||
for (char y = 0; y < 4; ++y) {
|
||||
result(x, y) = matrix[x][y];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DAEToEggConverter::apply_transform(const PT(EggGroup) to, const FCDTransform* from) {
|
||||
assert(from != NULL);
|
||||
assert(to != NULL);
|
||||
switch (from->GetType()) {
|
||||
case FCDTransform::TRANSLATION:
|
||||
to->add_translate3d(TO_VEC3(((FCDTTranslation*) from)->GetTranslation()));
|
||||
break;
|
||||
case FCDTransform::ROTATION:
|
||||
to->add_rotate3d(((FCDTRotation*) from)->GetAngle(), TO_VEC3(((FCDTRotation*) from)->GetAxis()));
|
||||
break;
|
||||
case FCDTransform::SCALE:
|
||||
to->add_scale3d(TO_VEC3(((FCDTScale*) from)->GetScale()));
|
||||
break;
|
||||
case FCDTransform::MATRIX:
|
||||
to->add_matrix4(convert_matrix(((FCDTMatrix*) from)->GetTransform()));
|
||||
break;
|
||||
default:
|
||||
// We don't know this, so let FCollada convert it into a matrix
|
||||
to->add_matrix4(convert_matrix(from->ToMatrix()));
|
||||
}
|
||||
}
|
84
pandatool/src/daeegg/daeToEggConverter.h
Executable file
84
pandatool/src/daeegg/daeToEggConverter.h
Executable file
@ -0,0 +1,84 @@
|
||||
// Filename: daeToEggConverter.h
|
||||
// Created by: pro-rsoft (08May08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DAETOEGGCONVERTER_H
|
||||
#define DAETOEGGCONVERTER_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "somethingToEggConverter.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggMaterial.h"
|
||||
#include "eggTexture.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggNurbsCurve.h"
|
||||
|
||||
#include "pre_fcollada_include.h"
|
||||
#include "FCollada.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDTransform.h"
|
||||
#include "FCDocument/FCDEntityInstance.h"
|
||||
#include "FCDocument/FCDControllerInstance.h"
|
||||
#include "FCDocument/FCDGeometryMesh.h"
|
||||
#include "FCDocument/FCDGeometrySpline.h"
|
||||
#include "FCDocument/FCDMaterial.h"
|
||||
#include "FMath/FMMatrix44.h"
|
||||
|
||||
#include "daeMaterials.h"
|
||||
#include "pvector.h" // Include last
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DAEToEggConverter
|
||||
// Description : This class supervises the construction of an
|
||||
// EggData structure from a DAE file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class DAEToEggConverter : public SomethingToEggConverter {
|
||||
public:
|
||||
DAEToEggConverter();
|
||||
DAEToEggConverter(const DAEToEggConverter ©);
|
||||
~DAEToEggConverter();
|
||||
|
||||
virtual SomethingToEggConverter *make_copy();
|
||||
|
||||
virtual string get_name() const;
|
||||
virtual string get_extension() const;
|
||||
|
||||
virtual bool convert_file(const Filename &filename);
|
||||
|
||||
private:
|
||||
|
||||
PT(EggTable) _table;
|
||||
FCDocument* _document;
|
||||
FUErrorSimpleHandler _error_handler;
|
||||
pmap<const string, PT(EggGroup)> _joints;
|
||||
pmap<const string, PT(EggVertexPool)> _vertex_pools;
|
||||
pvector<string> _skeletons;
|
||||
int _frame_rate;
|
||||
|
||||
void process_asset();
|
||||
void preprocess(const FCDSceneNode* node = NULL);
|
||||
void process_node(PT(EggGroupNode) parent, const FCDSceneNode* node, bool forced = false);
|
||||
void process_instance(PT(EggGroup) parent, const FCDEntityInstance* instance);
|
||||
void process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* mesh, PT(DaeMaterials) materials);
|
||||
void process_spline(PT(EggGroup) parent, const string group_name, FCDGeometrySpline* geometry_spline);
|
||||
void process_spline(PT(EggGroup) parent, const FCDSpline* spline);
|
||||
void process_controller(PT(EggGroup) parent, const FCDControllerInstance* instance);
|
||||
//void process_table_joint(PT(EggTable) parent, FCDSceneNode* node);
|
||||
|
||||
static LMatrix4d convert_matrix(const FMMatrix44& matrix);
|
||||
void apply_transform(const PT(EggGroup) to, const FCDTransform* from);
|
||||
|
||||
friend class DaeCharacter;
|
||||
};
|
||||
|
||||
#endif
|
5
pandatool/src/daeegg/daeegg_composite1.cxx
Executable file
5
pandatool/src/daeegg/daeegg_composite1.cxx
Executable file
@ -0,0 +1,5 @@
|
||||
|
||||
#include "config_daeegg.cxx"
|
||||
#include "daeCharacter.cxx"
|
||||
#include "daeMaterials.cxx"
|
||||
#include "daeToEggConverter.cxx"
|
26
pandatool/src/daeegg/pre_fcollada_include.h
Executable file
26
pandatool/src/daeegg/pre_fcollada_include.h
Executable file
@ -0,0 +1,26 @@
|
||||
// Filename: pre_fcollada_include.h
|
||||
// Created by: pro-rsoft (04Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file defines some stuff that need to be defined before
|
||||
// one includes FCollada.h
|
||||
|
||||
// FCollada expects LINUX to be defined on linux
|
||||
#ifdef IS_LINUX
|
||||
#ifndef LINUX
|
||||
#define LINUX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NO_LIBXML
|
||||
#define FCOLLADA_NOMINMAX
|
25
pandatool/src/daeprogs/Sources.pp
Executable file
25
pandatool/src/daeprogs/Sources.pp
Executable file
@ -0,0 +1,25 @@
|
||||
#define BUILD_DIRECTORY $[HAVE_FCOLLADA]
|
||||
|
||||
#define OTHER_LIBS \
|
||||
egg:c pandaegg:m \
|
||||
pipeline:c pnmimage:c putil:c event:c mathutil:c linmath:c panda:m \
|
||||
pandabase:c express:c pandaexpress:m \
|
||||
interrogatedb:c dtoolutil:c dtoolbase:c prc:c dconfig:c dtoolconfig:m dtool:m pystub
|
||||
|
||||
#begin bin_target
|
||||
#define TARGET dae2egg
|
||||
#define LOCAL_LIBS daeegg eggbase progbase
|
||||
|
||||
#define SOURCES \
|
||||
daeToEgg.cxx daeToEgg.h
|
||||
|
||||
#end bin_target
|
||||
|
||||
#begin bin_target
|
||||
#define TARGET egg2dae
|
||||
#define LOCAL_LIBS daeegg eggbase progbase
|
||||
|
||||
#define SOURCES \
|
||||
eggToDAE.cxx eggToDAE.h
|
||||
|
||||
#end bin_target
|
74
pandatool/src/daeprogs/daeToEgg.cxx
Executable file
74
pandatool/src/daeprogs/daeToEgg.cxx
Executable file
@ -0,0 +1,74 @@
|
||||
// Filename: daeToEgg.cxx
|
||||
// Created by: pro-rsoft (08May08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "daeToEgg.h"
|
||||
|
||||
#include "daeToEggConverter.h"
|
||||
#include "pystub.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEgg::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DAEToEgg::
|
||||
DAEToEgg():
|
||||
SomethingToEgg("COLLADA", ".dae")
|
||||
{
|
||||
add_units_options();
|
||||
add_normals_options();
|
||||
add_transform_options();
|
||||
|
||||
set_program_description
|
||||
("This program converts .dae files (COLLADA Digital Asset Exchange) to .egg.");
|
||||
|
||||
_coordinate_system = CS_yup_right;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DAEToEgg::run
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DAEToEgg::
|
||||
run() {
|
||||
nout << "Reading " << _input_filename << "\n";
|
||||
|
||||
_data->set_coordinate_system(_coordinate_system);
|
||||
|
||||
DAEToEggConverter converter;
|
||||
converter.set_egg_data(_data);
|
||||
converter._allow_errors = _allow_errors;
|
||||
|
||||
apply_parameters(converter);
|
||||
|
||||
if (!converter.convert_file(_input_filename)) {
|
||||
nout << "Errors in conversion.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
write_egg_file();
|
||||
nout << "\n";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// A call to pystub() to force libpystub.so to be linked in.
|
||||
pystub();
|
||||
|
||||
DAEToEgg prog;
|
||||
prog.parse_command_line(argc, argv);
|
||||
prog.run();
|
||||
return 0;
|
||||
}
|
35
pandatool/src/daeprogs/daeToEgg.h
Executable file
35
pandatool/src/daeprogs/daeToEgg.h
Executable file
@ -0,0 +1,35 @@
|
||||
// Filename: daeToEgg.h
|
||||
// Created by: pro-rsoft (08May08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DAETOEGG_H
|
||||
#define DAETOEGG_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "somethingToEgg.h"
|
||||
#include "daeToEggConverter.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DAEToEgg
|
||||
// Description : A program to read a DAE file and generate an egg
|
||||
// file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class DAEToEgg : public SomethingToEgg {
|
||||
public:
|
||||
DAEToEgg();
|
||||
|
||||
void run();
|
||||
};
|
||||
|
||||
#endif
|
182
pandatool/src/daeprogs/eggToDAE.cxx
Executable file
182
pandatool/src/daeprogs/eggToDAE.cxx
Executable file
@ -0,0 +1,182 @@
|
||||
// Filename: eggToDAE.cxx
|
||||
// Created by: pro-rsoft (04Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "eggToDAE.h"
|
||||
#include "dcast.h"
|
||||
#include "pystub.h"
|
||||
#include "pandaVersion.h"
|
||||
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAsset.h"
|
||||
#include "FCDocument/FCDTransform.h"
|
||||
|
||||
// Useful conversion stuff
|
||||
#define TO_VEC3(v) (LVecBase3d(v[0], v[1], v[2]))
|
||||
#define TO_VEC4(v) (LVecBase4d(v[0], v[1], v[2], v[3]))
|
||||
#define TO_COLOR(v) (Colorf(v[0], v[1], v[2], v[3]))
|
||||
#define FROM_VEC3(v) (FMVector3(v[0], v[1], v[2]))
|
||||
#define FROM_VEC4(v) (FMVector4(v[0], v[1], v[2], v[3]))
|
||||
#define FROM_MAT4(v) (FMMatrix44(v.get_data()))
|
||||
#define FROM_FSTRING(fs) (fs.c_str())
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggToDAE::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggToDAE::
|
||||
EggToDAE() :
|
||||
EggToSomething("COLLADA", ".dae", true, false)
|
||||
{
|
||||
set_binary_output(false);
|
||||
set_program_description
|
||||
("This program converts files from the egg format to the COLLADA "
|
||||
".dae (Digital Asset Exchange) format.");
|
||||
|
||||
_document = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggToDAE::run
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggToDAE::
|
||||
run() {
|
||||
nassertv(has_output_filename());
|
||||
nassertv(_data != NULL);
|
||||
|
||||
FCollada::Initialize();
|
||||
_document = FCollada::NewTopDocument();
|
||||
|
||||
// Add the contributor part to the asset
|
||||
FCDAssetContributor* contributor = _document->GetAsset()->AddContributor();
|
||||
const char* user_name = getenv("USER");
|
||||
if (user_name == NULL) user_name = getenv("USERNAME");
|
||||
if (user_name != NULL) contributor->SetAuthor(TO_FSTRING(user_name));
|
||||
//contributor->SetSourceData();
|
||||
char authoring_tool[1024];
|
||||
snprintf(authoring_tool, 1024, "Panda3D %s eggToDAE converter | FCollada v%d.%02d", PANDA_VERSION_STR, FCOLLADA_VERSION >> 16, FCOLLADA_VERSION & 0xFFFF);
|
||||
authoring_tool[1023] = 0;
|
||||
contributor->SetAuthoringTool(TO_FSTRING(authoring_tool));
|
||||
|
||||
// Set coordinate system
|
||||
switch (_data->get_coordinate_system()) {
|
||||
case CS_zup_right:
|
||||
_document->GetAsset()->SetUpAxis(FMVector3::ZAxis);
|
||||
break;
|
||||
case CS_yup_right:
|
||||
_document->GetAsset()->SetUpAxis(FMVector3::YAxis);
|
||||
break;
|
||||
}
|
||||
|
||||
// Now actually start processing the data.
|
||||
FCDSceneNode* visual_scene = _document->AddVisualScene();
|
||||
for (EggGroupNode::iterator it = _data->begin(); it != _data->end(); ++it) {
|
||||
if ((*it)->is_of_type(EggGroup::get_class_type())) {
|
||||
process_node(visual_scene, DCAST(EggGroup, *it));
|
||||
}
|
||||
}
|
||||
|
||||
// We're done here.
|
||||
FCollada::SaveDocument(_document, get_output_filename().to_os_specific().c_str());
|
||||
SAFE_DELETE(_document);
|
||||
FCollada::Release();
|
||||
|
||||
//if (!out) {
|
||||
// nout << "An error occurred while writing.\n";
|
||||
// exit(1);
|
||||
//}
|
||||
}
|
||||
|
||||
void EggToDAE::process_node(FCDSceneNode* parent, const PT(EggGroup) node) {
|
||||
assert(node != NULL);
|
||||
FCDSceneNode* scene_node = parent->AddChildNode();
|
||||
// Set the parameters
|
||||
scene_node->SetDaeId(node->get_name().c_str());
|
||||
scene_node->SetJointFlag(node->is_joint());
|
||||
// Apply the transforms
|
||||
apply_transform(scene_node, node);
|
||||
// Recursively process sub-nodes
|
||||
for (EggGroupNode::iterator it = node->begin(); it != node->end(); ++it) {
|
||||
if ((*it)->is_of_type(EggGroup::get_class_type())) {
|
||||
process_node(scene_node, DCAST(EggGroup, *it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EggToDAE::apply_transform(FCDSceneNode* to, const PT(EggGroup) from) {
|
||||
assert(to != NULL);
|
||||
assert(from != NULL);
|
||||
for (int co = 0; co < from->get_num_components(); ++co) {
|
||||
switch (from->get_component_type(co)) {
|
||||
case EggTransform::CT_translate2d:
|
||||
cerr << "Warning: ignoring non-supported 2d translation\n";
|
||||
break;
|
||||
case EggTransform::CT_rotate2d:
|
||||
cerr << "Warning: ignoring non-supported 2d rotation\n";
|
||||
break;
|
||||
case EggTransform::CT_scale2d:
|
||||
cerr << "Warning: ignoring non-supported 2d scaling\n";
|
||||
break;
|
||||
case EggTransform::CT_matrix3:
|
||||
cerr << "Warning: ignoring non-supported 2d matrix\n";
|
||||
break;
|
||||
case EggTransform::CT_translate3d: {
|
||||
FCDTTranslation* new_transform = (FCDTTranslation*) to->AddTransform(FCDTransform::TRANSLATION);
|
||||
new_transform->SetTranslation(FROM_VEC3(from->get_component_vec3(co)));
|
||||
break; }
|
||||
case EggTransform::CT_rotate3d: {
|
||||
FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION);
|
||||
new_transform->SetRotation(FROM_VEC3(from->get_component_vec3(co)), from->get_component_number(co));
|
||||
break; }
|
||||
case EggTransform::CT_scale3d: {
|
||||
FCDTScale* new_transform = (FCDTScale*) to->AddTransform(FCDTransform::SCALE);
|
||||
new_transform->SetScale(FROM_VEC3(from->get_component_vec3(co)));
|
||||
break; }
|
||||
case EggTransform::CT_matrix4: {
|
||||
FCDTMatrix* new_transform = (FCDTMatrix*) to->AddTransform(FCDTransform::MATRIX);
|
||||
new_transform->SetTransform(FROM_MAT4(from->get_component_mat4(co)));
|
||||
break; }
|
||||
case EggTransform::CT_rotx: {
|
||||
FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION);
|
||||
new_transform->SetRotation(FMVector3::XAxis, from->get_component_number(co));
|
||||
break; }
|
||||
case EggTransform::CT_roty: {
|
||||
FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION);
|
||||
new_transform->SetRotation(FMVector3::YAxis, from->get_component_number(co));
|
||||
break; }
|
||||
case EggTransform::CT_rotz: {
|
||||
FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION);
|
||||
new_transform->SetRotation(FMVector3::ZAxis, from->get_component_number(co));
|
||||
break; }
|
||||
case EggTransform::CT_uniform_scale: {
|
||||
FCDTScale* new_transform = (FCDTScale*) to->AddTransform(FCDTransform::SCALE);
|
||||
new_transform->SetScale(from->get_component_number(co), from->get_component_number(co), from->get_component_number(co));
|
||||
break; }
|
||||
default:
|
||||
cerr << "Warning: ignoring invalid transform\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// A call to pystub() to force libpystub.so to be linked in.
|
||||
pystub();
|
||||
|
||||
EggToDAE prog;
|
||||
prog.parse_command_line(argc, argv);
|
||||
prog.run();
|
||||
return 0;
|
||||
}
|
46
pandatool/src/daeprogs/eggToDAE.h
Executable file
46
pandatool/src/daeprogs/eggToDAE.h
Executable file
@ -0,0 +1,46 @@
|
||||
// Filename: eggToDAE.h
|
||||
// Created by: pro-rsoft (04Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EGGTODAE_H
|
||||
#define EGGTODAE_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "eggToSomething.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggTransform.h"
|
||||
|
||||
#include "pre_fcollada_include.h"
|
||||
#include "FCollada.h"
|
||||
#include "FCDocument/FCDSceneNode.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggToDAE
|
||||
// Description : A program to read an egg file and write a DAE file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EggToDAE : public EggToSomething {
|
||||
public:
|
||||
EggToDAE();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
FCDocument* _document;
|
||||
|
||||
void process_node(FCDSceneNode* parent, const PT(EggGroup) node);
|
||||
void apply_transform(FCDSceneNode* to, const PT(EggGroup) from);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user