From d447ec3bc60cf923d572be2e1b0fee75838bc650 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 15 Feb 2015 14:19:47 +0100 Subject: [PATCH 01/20] If GL_RENDERER begins with "Gallium", disable GL_PRIMITIVE_RESTART_FIXED_INDEX --- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 8845d69f61..76087d4644 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -558,10 +558,13 @@ reset() { _glPrimitiveRestartIndex = NULL; if (gl_support_primitive_restart_index) { - if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_ES3_compatibility")) { + if ((is_at_least_gl_version(4, 3) || has_extension("GL_ARB_ES3_compatibility")) && + _gl_renderer.substr(0, 7) != "Gallium") { // As long as we enable this, OpenGL will always use the highest possible index // for a numeric type as strip cut index, which coincides with our convention. - // This saves us a call to glPrimitiveRestartIndex. + // This saves us a call to glPrimitiveRestartIndex + // ... of course, though, the Gallium driver bugs out here. See also: + // https://www.panda3d.org/forums/viewtopic.php?f=5&t=17512 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); _supported_geom_rendering |= Geom::GR_strip_cut_index; From 0fda35d88c9fdef9fbb423b3288111dd82b93f97 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 16 Feb 2015 21:33:38 +0100 Subject: [PATCH 02/20] Commit patch by nikolm to support AmbientLight shader inputs in GLSL --- panda/src/display/graphicsStateGuardian.cxx | 65 ++++++++++++++------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 6dda4cb69a..1263339604 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1407,22 +1407,29 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation"); if (attrib == IN_ambient) { -#ifndef NDEBUG Light *light = np.node()->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ident_mat()); -#endif - // Lights don't currently have an ambient color in Panda3D. - // We still have to support the attribute. - t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f)); + if (np.node()->is_of_type(AmbientLight::get_class_type())) { + LColor c = light->get_color(); + c.componentwise_mult(_light_color_scale); + t.set_row(3, c); + } else { + // Non-ambient lights don't currently have an ambient color in Panda3D. + t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f)); + } return &t; } else if (attrib == IN_diffuse) { Light *light = np.node()->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ones_mat()); - - LColor c = light->get_color(); - c.componentwise_mult(_light_color_scale); - t.set_row(3, c); + if (np.node()->is_of_type(AmbientLight::get_class_type())) { + // Ambient light has no diffuse color. + t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f)); + } else { + LColor c = light->get_color(); + c.componentwise_mult(_light_color_scale); + t.set_row(3, c); + } return &t; } else if (attrib == IN_specular) { @@ -1432,7 +1439,11 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, return &t; } else if (attrib == IN_position) { - if (np.node()->is_of_type(DirectionalLight::get_class_type())) { + if (np.node()->is_of_type(AmbientLight::get_class_type())) { + // Ambient light has no position. + t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + return &t; + } else if (np.node()->is_of_type(DirectionalLight::get_class_type())) { DirectionalLight *light; DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); @@ -1458,7 +1469,11 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, } } else if (attrib == IN_halfVector) { - if (np.node()->is_of_type(DirectionalLight::get_class_type())) { + if (np.node()->is_of_type(AmbientLight::get_class_type())) { + // Ambient light has no half-vector. + t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + return &t; + } else if (np.node()->is_of_type(DirectionalLight::get_class_type())) { DirectionalLight *light; DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); @@ -1490,19 +1505,25 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, } } else if (attrib == IN_spotDirection) { - LightLensNode *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); - Lens *lens = light->get_lens(); - nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); + if (np.node()->is_of_type(AmbientLight::get_class_type())) { + // Ambient light has no spot direction. + t.set_row(3, LVector3(0.0f, 0.0f, 0.0f)); + return &t; + } else { + LightLensNode *light; + DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + Lens *lens = light->get_lens(); + nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); - CPT(TransformState) transform = - get_scene()->get_cs_world_transform()->compose( - np.get_transform(_scene_setup->get_scene_root().get_parent())); + CPT(TransformState) transform = + get_scene()->get_cs_world_transform()->compose( + np.get_transform(_scene_setup->get_scene_root().get_parent())); - const LMatrix4 &light_mat = transform->get_mat(); - LVector3 dir = lens->get_view_vector() * light_mat; - t.set_row(3, dir); - return &t; + const LMatrix4 &light_mat = transform->get_mat(); + LVector3 dir = lens->get_view_vector() * light_mat; + t.set_row(3, dir); + return &t; + } } else if (attrib == IN_spotCutoff) { if (np.node()->is_of_type(Spotlight::get_class_type())) { From b7ef0d3bc39d78e1794674c8db929b18d267d0fa Mon Sep 17 00:00:00 2001 From: enn0x Date: Fri, 20 Feb 2015 01:14:12 +0100 Subject: [PATCH 03/20] Exposed flag to disable collision between linked bodies. --- panda/src/bullet/bulletWorld.cxx | 9 +++++---- panda/src/bullet/bulletWorld.h | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/panda/src/bullet/bulletWorld.cxx b/panda/src/bullet/bulletWorld.cxx index 07a891aa4c..bee0b72f39 100644 --- a/panda/src/bullet/bulletWorld.cxx +++ b/panda/src/bullet/bulletWorld.cxx @@ -608,11 +608,12 @@ remove_vehicle(BulletVehicle *vehicle) { //////////////////////////////////////////////////////////////////// // Function: BulletWorld::attach_constraint // Access: Published -// Description: Deprecated! -// Please use BulletWorld::attach +// Description: Attaches a single constraint to a world. Collision +// checks between the linked objects will be disabled +// if the second parameter is set to TRUE. //////////////////////////////////////////////////////////////////// void BulletWorld:: -attach_constraint(BulletConstraint *constraint) { +attach_constraint(BulletConstraint *constraint, bool linked_collision) { nassertv(constraint); @@ -622,7 +623,7 @@ attach_constraint(BulletConstraint *constraint) { if (found == _constraints.end()) { _constraints.push_back(constraint); - _world->addConstraint(constraint->ptr()); + _world->addConstraint(constraint->ptr(), linked_collision); } else { bullet_cat.warning() << "constraint already attached" << endl; diff --git a/panda/src/bullet/bulletWorld.h b/panda/src/bullet/bulletWorld.h index 6a798cde7f..88fca5abd1 100644 --- a/panda/src/bullet/bulletWorld.h +++ b/panda/src/bullet/bulletWorld.h @@ -70,6 +70,8 @@ PUBLISHED: // Attach/Remove void attach(TypedObject *object); + void attach_constraint(BulletConstraint *constraint, bool linked_collision=false); + void remove(TypedObject *object); // Ghost object @@ -172,7 +174,6 @@ PUBLISHED: // Deprecated methods, will become private soon void attach_character(BulletBaseCharacterControllerNode *node); void remove_character(BulletBaseCharacterControllerNode *node); - void attach_constraint(BulletConstraint *constraint); void remove_constraint(BulletConstraint *constraint); public: From d320aced735d4b63bceeab8b845148ee713a9f1d Mon Sep 17 00:00:00 2001 From: enn0x Date: Fri, 20 Feb 2015 01:29:16 +0100 Subject: [PATCH 04/20] Fixed const-correctness for BulletAllHitRayResult. --- panda/src/bullet/bulletAllHitsRayResult.cxx | 2 +- panda/src/bullet/bulletAllHitsRayResult.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/panda/src/bullet/bulletAllHitsRayResult.cxx b/panda/src/bullet/bulletAllHitsRayResult.cxx index 953390820e..7d57feb767 100644 --- a/panda/src/bullet/bulletAllHitsRayResult.cxx +++ b/panda/src/bullet/bulletAllHitsRayResult.cxx @@ -156,7 +156,7 @@ get_hit_fraction() const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -PandaNode *BulletRayHit:: +const PandaNode *BulletRayHit:: get_node() const { return (_object) ? (PandaNode *)_object->getUserPointer() : NULL; diff --git a/panda/src/bullet/bulletAllHitsRayResult.h b/panda/src/bullet/bulletAllHitsRayResult.h index 6825e0ff68..26e04034af 100644 --- a/panda/src/bullet/bulletAllHitsRayResult.h +++ b/panda/src/bullet/bulletAllHitsRayResult.h @@ -33,7 +33,7 @@ struct EXPCL_PANDABULLET BulletRayHit { PUBLISHED: INLINE static BulletRayHit empty(); - PandaNode *get_node() const; + const PandaNode *get_node() const; LPoint3 get_hit_pos() const; LVector3 get_hit_normal() const; PN_stdfloat get_hit_fraction() const; From 2dd1b5e3b3113dd30336ebcc069588944dec580d Mon Sep 17 00:00:00 2001 From: deflected Date: Fri, 20 Feb 2015 11:58:28 +0200 Subject: [PATCH 05/20] dtool: Fixed building under FreeBSD There is missing define in dtoolutil which prevent building of dtool under FreeBSD. Signed-off-by: deflected --- dtool/src/dtoolutil/executionEnvironment.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index 059bce8fcd..3f06a3427f 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -60,7 +60,7 @@ extern char **environ; #include #endif -#if defined(IS_LINUX) || defined(IS_OSX) +#if defined(IS_LINUX) || defined(IS_OSX) || defined(IS_FREEBSD) // For link_map and dlinfo. #include #include From d82f2c83cdf81b3cd45e1c61a335d439f11805be Mon Sep 17 00:00:00 2001 From: deflected Date: Fri, 20 Feb 2015 13:59:35 +0200 Subject: [PATCH 06/20] downloader: Correct lack of timezone - Use tm_gmtoff for GMT correction under FreeBSD Signed-off-by: deflected --- panda/src/downloader/httpDate.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/panda/src/downloader/httpDate.cxx b/panda/src/downloader/httpDate.cxx index fd9d01e8ed..ea143e0bfa 100644 --- a/panda/src/downloader/httpDate.cxx +++ b/panda/src/downloader/httpDate.cxx @@ -223,8 +223,14 @@ HTTPDate(const string &format) { if (_time != (time_t)-1) { // Unfortunately, mktime() assumes local time; convert this back // to GMT. +#ifdef IS_FREEBSD + time_t now = time(NULL); + struct tm *tp = localtime(&now); + _time -= tp->tm_gmtoff; +#else /* IS_FREEBSD */ extern long int timezone; _time -= timezone; +#endif /* IS_FREEBSD */ } #endif // __GNUC__ } From 3600abfe6db5ef79a149179fadfa750dcc4859e7 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 22 Feb 2015 13:51:46 +0100 Subject: [PATCH 07/20] Fix coercion of non-interned strings in Python 3 --- panda/src/gobj/internalName_ext.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/gobj/internalName_ext.cxx b/panda/src/gobj/internalName_ext.cxx index 5d15fd5e6d..dfdb8e8e36 100644 --- a/panda/src/gobj/internalName_ext.cxx +++ b/panda/src/gobj/internalName_ext.cxx @@ -36,7 +36,7 @@ make(PyUnicodeObject *str) { } string name(c_str, len); - return InternalName::make(c_str, len); + return InternalName::make(name); } InternalName::PyInternTable::const_iterator it; From 6263a591be0174543c866b389278107df5052bd5 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 22 Feb 2015 15:04:54 +0100 Subject: [PATCH 08/20] Fix matrix.almost_equal with custom threshold in Eigen build --- panda/src/linmath/lmatrix3_src.cxx | 2 +- panda/src/linmath/lmatrix4_src.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/panda/src/linmath/lmatrix3_src.cxx b/panda/src/linmath/lmatrix3_src.cxx index 6906aa503f..994056de79 100644 --- a/panda/src/linmath/lmatrix3_src.cxx +++ b/panda/src/linmath/lmatrix3_src.cxx @@ -353,7 +353,7 @@ bool FLOATNAME(LMatrix3):: almost_equal(const FLOATNAME(LMatrix3) &other, FLOATTYPE threshold) const { TAU_PROFILE("bool LMatrix3::almost_equal(const LMatrix3 &, FLOATTYPE)", " ", TAU_USER); #ifdef HAVE_EIGEN - return ((_m - other._m).cwiseAbs().maxCoeff() < NEARLY_ZERO(FLOATTYPE)); + return ((_m - other._m).cwiseAbs().maxCoeff() < threshold); #else return (IS_THRESHOLD_EQUAL((*this)(0, 0), other(0, 0), threshold) && IS_THRESHOLD_EQUAL((*this)(0, 1), other(0, 1), threshold) && diff --git a/panda/src/linmath/lmatrix4_src.cxx b/panda/src/linmath/lmatrix4_src.cxx index 4123fd17aa..75775f9217 100644 --- a/panda/src/linmath/lmatrix4_src.cxx +++ b/panda/src/linmath/lmatrix4_src.cxx @@ -296,7 +296,7 @@ bool FLOATNAME(LMatrix4):: almost_equal(const FLOATNAME(LMatrix4) &other, FLOATTYPE threshold) const { TAU_PROFILE("bool LMatrix4::almost_equal(const LMatrix4 &, FLOATTYPE)", " ", TAU_USER); #ifdef HAVE_EIGEN - return ((_m - other._m).cwiseAbs().maxCoeff() < NEARLY_ZERO(FLOATTYPE)); + return ((_m - other._m).cwiseAbs().maxCoeff() < threshold); #else return (IS_THRESHOLD_EQUAL((*this)(0, 0), other(0, 0), threshold) && IS_THRESHOLD_EQUAL((*this)(0, 1), other(0, 1), threshold) && From 9aafde057935b2f27356e1b30054b4bdf5f5cad4 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 24 Feb 2015 14:59:32 +0100 Subject: [PATCH 09/20] Add animation support to dae2egg --- pandatool/src/daeegg/daeCharacter.cxx | 328 +++++++++-- pandatool/src/daeegg/daeCharacter.h | 55 +- pandatool/src/daeegg/daeMaterials.cxx | 21 +- pandatool/src/daeegg/daeToEggConverter.cxx | 617 +++++++++++++-------- pandatool/src/daeegg/daeToEggConverter.h | 43 +- pandatool/src/daeprogs/daeToEgg.cxx | 8 + 6 files changed, 759 insertions(+), 313 deletions(-) diff --git a/pandatool/src/daeegg/daeCharacter.cxx b/pandatool/src/daeegg/daeCharacter.cxx index cb2633653a..d3c091d7bf 100644 --- a/pandatool/src/daeegg/daeCharacter.cxx +++ b/pandatool/src/daeegg/daeCharacter.cxx @@ -17,88 +17,316 @@ #include "fcollada_utils.h" #include "pt_EggVertex.h" #include "eggXfmSAnim.h" +#include "daeToEggConverter.h" +#include "daeMaterials.h" + +#include "eggExternalReference.h" #include "FCDocument/FCDocument.h" #include "FCDocument/FCDController.h" +#include "FCDocument/FCDGeometry.h" #include "FCDocument/FCDSceneNodeTools.h" +#include "FCDocument/FCDSceneNode.h" +#include "FCDocument/FCDTransform.h" +#include "FCDocument/FCDAnimated.h" +#include "FCDocument/FCDAnimationCurve.h" +#include "FCDocument/FCDAnimationKey.h" + TypeHandle DaeCharacter::_type_handle; //////////////////////////////////////////////////////////////////// // Function: DaeCharacter::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// DaeCharacter:: -DaeCharacter(const string name, const FCDControllerInstance* controller_instance) { - _controller_instance = (FCDControllerInstance*) controller_instance; - _name = name; - _frame_rate = 0; - _skin_controller = NULL; +DaeCharacter(EggGroup *node_group, const FCDControllerInstance *instance) : + _node_group(node_group), + _name(node_group->get_name()), + _instance(instance), + _skin_controller(NULL), + _skin_mesh(NULL) { + + _bind_shape_mat = LMatrix4d::ident_mat(); + // If it's a skin controller, add the controller joints. - FCDController* controller = (FCDController*) controller_instance->GetEntity(); - if (controller == NULL) return; + const FCDController *controller = (const FCDController *)instance->GetEntity(); + if (controller == NULL) { + return; + } + _skin_mesh = controller->GetBaseGeometry()->GetMesh(); + 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); + _bind_shape_mat = DAEToEggConverter::convert_matrix(_skin_controller->GetBindShapeTransform()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DaeCharacter::bind_joints +// Access: Public +// Description: Binds the joints to the character. This means +// changing them to the bind pose. It is necessary +// to call this before process_skin_geometry. +// +// Returns the root group. +//////////////////////////////////////////////////////////////////// +void DaeCharacter:: +bind_joints(JointMap &joint_map) { + _joints.clear(); + + size_t num_joints = _skin_controller->GetJointCount(); + _joints.reserve(num_joints); + + // Record the bind pose for each joint. + for (size_t j = 0; j < num_joints; ++j) { + const FCDSkinControllerJoint *skin_joint = _skin_controller->GetJoint(j); + string sid = FROM_FSTRING(skin_joint->GetId()); + LMatrix4d bind_pose; + bind_pose.invert_from(DAEToEggConverter::convert_matrix( + skin_joint->GetBindPoseInverse())); + + // Check that we already encountered this joint during traversal. + JointMap::iterator ji = joint_map.find(sid); + if (ji != joint_map.end()) { + Joint &joint = ji->second; + + if (joint._character != (DaeCharacter *)NULL) { + // In some cases, though, multiple controllers share the same joints. + // We can't support this without duplicating the joint structure, + // so we check if the bind poses are the same. + if (!joint._bind_pose.almost_equal(bind_pose, 0.0001)) { + // Ugh. What else could we do? + daeegg_cat.error() + << "Multiple controllers share joint with sid " << sid + << ", with different bind poses.\n"; + } + } else { + // Mark the joint as being controlled by this character. + joint._bind_pose = bind_pose; + joint._character = this; + } + + _joints.push_back(joint); + } else { + daeegg_cat.warning() + << "Unknown joint sid being referenced: '" << sid << "'\n"; + + // We still have to add a dummy joint or the index will be off. + _joints.push_back(Joint(NULL, NULL)); } } } //////////////////////////////////////////////////////////////////// -// Function: DaeCharacter::as_egg_bundle +// Function: DaeCharacter::adjust_joints // Access: Public -// Description: Returns the character as a element, -// suited for the animation table. +// Description: Traverses through the character hierarchy in order +// to bind the mesh to the character. This involves +// reorienting the joints to match the bind pose. +// +// It is important that this is called only once. //////////////////////////////////////////////////////////////////// -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->set_table_type(EggTable::TT_table); - bundle->add_child(skeleton); - // Loop through the joint hierarchy -#if FCOLLADA_VERSION < 0x00030005 - FCDSceneNodeList roots = _controller_instance->FindSkeletonNodes(); -#else - FCDSceneNodeList roots; - _controller_instance->FindSkeletonNodes(roots); -#endif - for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) { - process_joint(skeleton, *it); +void DaeCharacter:: +adjust_joints(FCDSceneNode *node, const JointMap &joint_map, + const LMatrix4d &transform) { + + LMatrix4d this_transform = transform; + + if (node->IsJoint()) { + string sid = FROM_FSTRING(node->GetSubId()); + + JointMap::const_iterator ji = joint_map.find(sid); + if (ji != joint_map.end()) { + const Joint &joint = ji->second; + + // Panda needs the joints to be in bind pose. Not fun! We copy the joint + // transform to the default pose, though, so that Panda will restore the + // joint transformation after binding. + + if (joint._character == this) { + LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat * + invert(transform); + //LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat * + // joint._group->get_parent()->get_node_frame_inv(); + + this_transform = bind_pose * this_transform; + joint._group->set_default_pose(*joint._group); + joint._group->set_transform3d(bind_pose); + + /* + PT(EggGroup) sphere = new EggGroup; + sphere->add_uniform_scale(0.1); + sphere->set_group_type(EggGroup::GT_instance); + sphere->add_child(new EggExternalReference("", "jack.egg")); + joint._group->add_child(sphere); + */ + } + } + } else { + //this_transform = DAEToEggConverter::convert_matrix(node->ToMatrix()); + } + + // Loop through the children joints + for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) { + //if (node->GetChild(ch)->IsJoint()) { + adjust_joints(node->GetChild(ch), joint_map, this_transform); + //} } - return bundle; } //////////////////////////////////////////////////////////////////// -// Function: DaeCharacter::process_joint +// Function: DaeCharacter::influence_vertex +// Access: Public +// Description: Adds the influences for the given vertex. +//////////////////////////////////////////////////////////////////// +void DaeCharacter:: +influence_vertex(int index, EggVertex *vertex) { + const FCDSkinControllerVertex *influence = _skin_controller->GetVertexInfluence(index); + + for (size_t pa = 0; pa < influence->GetPairCount(); ++pa) { + const FCDJointWeightPair* jwpair = influence->GetPair(pa); + + if (jwpair->jointIndex >= 0 && jwpair->jointIndex < _joints.size()) { + EggGroup *joint = _joints[jwpair->jointIndex]._group.p(); + if (joint != NULL) { + joint->ref_vertex(vertex, jwpair->weight); + } + } else { + daeegg_cat.error() + << "Invalid joint index: " << jwpair->jointIndex << "\n"; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DaeCharacter::collect_keys +// Access: Public +// Description: Collects all animation keys of animations applied +// to this character. +//////////////////////////////////////////////////////////////////// +void DaeCharacter:: +collect_keys(pset &keys) { +#if FCOLLADA_VERSION < 0x00030005 + FCDSceneNodeList roots = _instance->FindSkeletonNodes(); +#else + FCDSceneNodeList roots; + _instance->FindSkeletonNodes(roots); +#endif + + for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) { + r_collect_keys(*it, keys); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DaeCharacter::r_collect_keys +// Access: Public +// Description: Collects all animation keys found for the given +// node tree. +//////////////////////////////////////////////////////////////////// +void DaeCharacter:: +r_collect_keys(FCDSceneNode* node, pset &keys) { + FCDAnimatedList animateds; + + // Collect all the animation curves + for (size_t t = 0; t < node->GetTransformCount(); ++t) { + FCDTransform *transform = node->GetTransform(t); + FCDAnimated *animated = transform->GetAnimated(); + + if (animated != NULL) { + const FCDAnimationCurveListList &all_curves = animated->GetCurves(); + + for (size_t ci = 0; ci < all_curves.size(); ++ci) { + const FCDAnimationCurveTrackList &curves = all_curves[ci]; + if (curves.empty()) { + continue; + } + + size_t num_keys = curves.front()->GetKeyCount(); + const FCDAnimationKey **curve_keys = curves.front()->GetKeys(); + + for (size_t c = 0; c < num_keys; ++c) { + keys.insert(curve_keys[c]->input); + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DaeCharacter::build_table // Access: Public // Description: Processes a joint node and its transforms. //////////////////////////////////////////////////////////////////// void DaeCharacter:: -process_joint(PT(EggTable) parent, FCDSceneNode* node) { +build_table(EggTable *parent, FCDSceneNode* node, const pset &keys) { 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)); + + if (!node->IsJoint()) { + for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) { + build_table(parent, node->GetChild(ch), keys); + } + return; } - // 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)); + + string node_id = FROM_FSTRING(node->GetDaeId()); + PT(EggTable) table = new EggTable(node_id); + table->set_table_type(EggTable::TT_table); + parent->add_child(table); + + PT(EggXfmSAnim) xform = new EggXfmSAnim("xform"); + table->add_child(xform); + + // Generate the sampled animation and loop through the matrices + FCDAnimatedList animateds; + + // Collect all the animation curves + for (size_t t = 0; t < node->GetTransformCount(); ++t) { + FCDTransform *transform = node->GetTransform(t); + FCDAnimated *animated = transform->GetAnimated(); + if (animated != (FCDAnimated *)NULL) { + if (animated->HasCurve()) { + animateds.push_back(animated); + } } } + + // Sample the scene node transform + float last_key; + float timing_total = 0; + pset::const_iterator ki; + for (ki = keys.begin(); ki != keys.end(); ++ki) { + for (FCDAnimatedList::iterator it = animateds.begin(); it != animateds.end(); ++it) { + // Sample each animated, which changes the transform values directly + (*it)->Evaluate(*ki); + } + + if (ki != keys.begin()) { + timing_total += (*ki - last_key); + } + last_key = *ki; + + // Retrieve the new transform matrix for the COLLADA scene node + FMMatrix44 fmat = node->ToMatrix(); + + // Work around issue in buggy exporters (like ColladaMax) + if (IS_NEARLY_ZERO(fmat[3][3])) { + fmat[3][3] = 1; + } + + xform->add_data(DAEToEggConverter::convert_matrix(fmat)); + } + + // Quantize the FPS, otherwise Panda complains about FPS mismatches. + float fps = round(((keys.size() - 1) / timing_total) * 100) * 0.01f; + xform->set_fps(fps); + + // Loop through the children joints + for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) { + //if (node->GetChild(ch)->IsJoint()) { + build_table(table, node->GetChild(ch), keys); + //} + } } diff --git a/pandatool/src/daeegg/daeCharacter.h b/pandatool/src/daeegg/daeCharacter.h index e7a85cbedf..cd656eae06 100644 --- a/pandatool/src/daeegg/daeCharacter.h +++ b/pandatool/src/daeegg/daeCharacter.h @@ -12,20 +12,22 @@ // //////////////////////////////////////////////////////////////////// +#ifndef DAECHARACTER_H +#define DAECHARACTER_H + #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" +#include "FCDocument/FCDGeometryMesh.h" -#ifndef DAECHARACTER_H -#define DAECHARACTER_H +class DAEToEggConverter; //////////////////////////////////////////////////////////////////// // Class : DaeCharacter @@ -33,17 +35,46 @@ //////////////////////////////////////////////////////////////////// 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); - + DaeCharacter(EggGroup *node_group, const FCDControllerInstance* controller_instance); + + struct Joint { + INLINE Joint(EggGroup *group, const FCDSceneNode *scene_node) : + _group(group), + _scene_node(scene_node), + _character(NULL), + _bind_pose(LMatrix4d::ident_mat()) {} + + LMatrix4d _bind_pose; + const PT(EggGroup) _group; + const FCDSceneNode *_scene_node; + DaeCharacter *_character; + }; + typedef pvector Joints; + typedef pmap JointMap; + + void bind_joints(JointMap &joint_map); + void adjust_joints(FCDSceneNode *node, const JointMap &joint_map, + const LMatrix4d &transform = LMatrix4d::ident_mat()); + + void influence_vertex(int index, EggVertex *vertex); + + void collect_keys(pset &keys); + void r_collect_keys(FCDSceneNode *node, pset &keys); + + void build_table(EggTable *parent, FCDSceneNode* node, const pset &keys); + +public: + PT(EggGroup) _node_group; + const FCDGeometryMesh *_skin_mesh; + const FCDControllerInstance *_instance; + LMatrix4d _bind_shape_mat; + private: - int _frame_rate; string _name; - FCDControllerInstance* _controller_instance; - FCDSkinController* _skin_controller; - pmap _controller_joints; - + const FCDSkinController *_skin_controller; + Joints _joints; + JointMap _bound_joints; + public: virtual TypeHandle get_type() const { return get_class_type(); diff --git a/pandatool/src/daeegg/daeMaterials.cxx b/pandatool/src/daeegg/daeMaterials.cxx index 4790c3bfc2..9d234489ab 100755 --- a/pandatool/src/daeegg/daeMaterials.cxx +++ b/pandatool/src/daeegg/daeMaterials.cxx @@ -35,7 +35,7 @@ TypeHandle DaeMaterials::_type_handle; //////////////////////////////////////////////////////////////////// // Function: DaeMaterials::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// DaeMaterials:: DaeMaterials(const FCDGeometryInstance* geometry_instance) { @@ -58,7 +58,7 @@ void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) { return; } _materials[semantic] = new DaeMaterial(); - + // Load in the uvsets for (size_t vib = 0; vib < instance->GetVertexInputBindingCount(); ++vib) { const FCDMaterialInstanceBindVertexInput* mivib = instance->GetVertexInputBinding(vib); @@ -74,7 +74,7 @@ void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) { #endif _materials[semantic]->_uvsets.push_back(bvi); } - + // Handle the material stuff daeegg_cat.spam() << "Trying to process material with semantic " << semantic << endl; PT_EggMaterial egg_material = new EggMaterial(semantic); @@ -204,12 +204,13 @@ process_extra(const string semantic, const FCDExtra* extra) { 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") { + string content = trim(enode->GetContent()); + if (content == "1" || content == "true") { _materials[semantic]->_double_sided = true; - } else if (trim(enode->GetContent()) == "0") { + } else if (content == "0" || content == "false") { _materials[semantic]->_double_sided = false; } else { - daeegg_cat.warning() << "Expected tag to be either 1 or 0, found '" << enode->GetContent() << "' instead" << endl; + daeegg_cat.warning() << "Expected tag to be either 1 or 0, found '" << content << "' instead" << endl; } } } @@ -391,7 +392,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen blend->_color = LColor::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; @@ -404,7 +405,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen blend->_enabled = false; return blend; } - + // Now figure out the operands. if (mode == FCDEffectStandard::RGB_ZERO) {// || mode == FCDEffectStandard::A_ZERO) { blend->_operand_a = EggGroup::BO_one_minus_constant_color; @@ -417,7 +418,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen blend->_enabled = false; return blend; } - + // See if we can optimize out the color. if (blend->_operand_a == EggGroup::BO_constant_color) { if (blend->_color == LColor::zero()) { @@ -447,7 +448,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen 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; diff --git a/pandatool/src/daeegg/daeToEggConverter.cxx b/pandatool/src/daeegg/daeToEggConverter.cxx index 320255e63b..8ff46b401b 100755 --- a/pandatool/src/daeegg/daeToEggConverter.cxx +++ b/pandatool/src/daeegg/daeToEggConverter.cxx @@ -56,9 +56,10 @@ //////////////////////////////////////////////////////////////////// DAEToEggConverter:: DAEToEggConverter() { + _unit_name = "meter"; + _unit_meters = 1.0; _document = NULL; _table = NULL; - _frame_rate = -1; _error_handler = NULL; _invert_transparency = false; } @@ -131,18 +132,15 @@ convert_file(const Filename &filename) { // Reset stuff clear_error(); _joints.clear(); - _vertex_pools.clear(); - _skeletons.clear(); - _frame_rate = -1; if (_error_handler == NULL) { _error_handler = new FUErrorSimpleHandler; } - + // 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()); @@ -155,201 +153,375 @@ convert_file(const Filename &filename) { if (_document->GetAsset() != NULL) { FCDocumentTools::StandardizeUpAxisAndLength(_document); } - - _table = new EggTable(); - _table->set_table_type(EggTable::TT_table); - // Process the stuff + + // Process the scene process_asset(); - preprocess(); + PT(EggGroup) scene_group; + string model_name = _character_name; + FCDSceneNode* visual_scene = _document->GetVisualSceneInstance(); if (visual_scene != NULL) { - // First check for an 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 tag: '" << enode->GetContent() << "'" << endl; - } } } } - // Now loop through the children + if (model_name.empty()) { + // By lack of anything better... + model_name = FROM_FSTRING(visual_scene->GetName()); + } + scene_group = new EggGroup(model_name); + _egg_data->add_child(scene_group); + for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) { - process_node(DCAST(EggGroupNode, _egg_data), visual_scene->GetChild(ch)); + process_node(scene_group, visual_scene->GetChild(ch)); + } + } else { + daeegg_cat.warning() + << "No visual scene instance found in COLLADA document.\n"; + } + + // Now process the characters. This depends on information from collected + // joints, which is why it's done in a second step. + if (get_animation_convert() != AC_none) { + Characters::iterator it; + DaeCharacter *character; + for (it = _characters.begin(); it != _characters.end(); ++it) { + character = *it; + if (get_animation_convert() != AC_chan) { + character->bind_joints(_joints); + + const FCDGeometryMesh *mesh = character->_skin_mesh; + + if (mesh != NULL) { + PT(DaeMaterials) materials = new DaeMaterials(character->_instance); + daeegg_cat.spam() << "Processing mesh for controller\n"; + process_mesh(character->_node_group, mesh, materials, character); + } + } + } + + // Put the joints in bind pose. + for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) { + character->adjust_joints(visual_scene->GetChild(ch), _joints, LMatrix4d::ident_mat()); + } + + if (scene_group != NULL) { + // Mark the scene as character. + if (get_animation_convert() == AC_chan) { + _egg_data->remove_child(scene_group); + } else { + scene_group->set_dart_type(EggGroup::DT_default); + } + } + + if (get_animation_convert() != AC_model) { + _table = new EggTable(); + _table->set_table_type(EggTable::TT_table); + _egg_data->add_child(_table); + + PT(EggTable) bundle = new EggTable(model_name); + bundle->set_table_type(EggTable::TT_bundle); + _table->add_child(bundle); + + PT(EggTable) skeleton = new EggTable(""); + skeleton->set_table_type(EggTable::TT_table); + bundle->add_child(skeleton); + + pset keys; + + Characters::iterator it; + DaeCharacter *character; + for (it = _characters.begin(); it != _characters.end(); ++it) { + DaeCharacter *character = *it; + + // Collect key frame timings. + if (get_animation_convert() == AC_both || + get_animation_convert() == AC_chan) { + character->collect_keys(keys); + } + } + + if (_frame_inc != 0.0) { + // A frame increment was given, this means that we have to sample the + // animation. + float start, end; + if (_end_frame != _start_frame) { + start = _start_frame; + end = _end_frame; + } else { + // No range was given. Infer the frame range from the keys. + start = *keys.begin(); + end = *keys.rbegin(); + } + keys.clear(); + + for (float t = start; t <= end; t += _frame_inc) { + keys.insert(t); + } + } else { + // No sampling parameters given; not necessarily a failure, since the + // animation may already be sampled. We use the key frames as animation + // frames. + if (_end_frame != 0.0) { + // An end frame was given, chop off all keys after that. + float end = _end_frame; + pset::iterator ki; + for (ki = keys.begin(); ki != keys.end(); ++ki) { + if (*ki > end && !IS_THRESHOLD_EQUAL(*ki, end, 0.001)) { + keys.erase(ki, keys.end()); + break; + } + } + } + if (_start_frame != 0.0) { + // A start frame was given, chop off all keys before that. + float start = _start_frame; + pset::iterator ki; + for (ki = keys.begin(); ki != keys.end(); ++ki) { + if (*ki > start && !IS_THRESHOLD_EQUAL(*ki, start, 0.001)) { + keys.erase(keys.begin(), ki); + break; + } + } + } + + // Check that this does indeed look like a sampled animation; if not, + // issue an appropriate warning. + pset::const_iterator ki = keys.begin(); + if (ki != keys.end()) { + float last = *ki; + float diff = 0; + + for (++ki; ki != keys.end(); ++ki) { + if (diff != 0 && !IS_THRESHOLD_EQUAL((*ki - last), diff, 0.001)) { + daeegg_cat.error() + << "This does not appear to be a sampled animation.\n" + << "Specify the -sf, -ef and -if options to indicate how the " + << "animations should be sampled.\n"; + break; + } + diff = (*ki - last); + last = *ki; + } + } + } + + // It doesn't really matter which character we grab for this as + // it'll iterate over the whole graph right now anyway. + for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) { + character->build_table(skeleton, visual_scene->GetChild(ch), keys); + } } } - SAFE_DELETE(visual_scene); - - _egg_data->add_child(_table); - + // Clean up and return + SAFE_DELETE(visual_scene); SAFE_DELETE(_document); FCollada::Release(); return true; } -void DAEToEggConverter::process_asset() { - if (_document->GetAsset() == NULL) return; +//////////////////////////////////////////////////////////////////// +// Function: DAEToEggConverter::get_input_units +// Access: Public, Virtual +// Description: This may be called after convert_file() has been +// called and returned true, indicating a successful +// conversion. It will return the distance units +// represented by the converted egg file, if known, or +// DU_invalid if not known. +//////////////////////////////////////////////////////////////////// +DistanceUnit DAEToEggConverter:: +get_input_units() { + if (IS_NEARLY_EQUAL(_unit_meters, 0.001)) { + return DU_millimeters; + } + if (IS_NEARLY_EQUAL(_unit_meters, 0.01)) { + return DU_centimeters; + } + if (IS_NEARLY_EQUAL(_unit_meters, 1.0)) { + return DU_meters; + } + if (IS_NEARLY_EQUAL(_unit_meters, 1000.0)) { + return DU_kilometers; + } + if (IS_NEARLY_EQUAL(_unit_meters, 3.0 * 12.0 * 0.0254)) { + return DU_yards; + } + if (IS_NEARLY_EQUAL(_unit_meters, 12.0 * 0.0254)) { + return DU_feet; + } + if (IS_NEARLY_EQUAL(_unit_meters, 0.0254)) { + return DU_inches; + } + if (IS_NEARLY_EQUAL(_unit_meters, 1852.0)) { + return DU_nautical_miles; + } + if (IS_NEARLY_EQUAL(_unit_meters, 5280.0 * 12.0 * 0.0254)) { + return DU_statute_miles; + } + + // Whatever. + return DU_invalid; +} + +void DAEToEggConverter:: +process_asset() { + const FCDAsset *asset = _document->GetAsset(); + if (_document->GetAsset() == NULL) { + return; + } + + _unit_name = FROM_FSTRING(asset->GetUnitName()); + _unit_meters = asset->GetUnitConversionFactor(); + // Read out the coordinate system - FMVector3 up_axis (_document->GetAsset()->GetUpAxis()); + FMVector3 up_axis = asset->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. -#if FCOLLADA_VERSION < 0x00030005 - FCDSceneNodeList roots = ((FCDControllerInstance*) node->GetInstance(in))->FindSkeletonNodes(); -#else - FCDSceneNodeList roots; - ((FCDControllerInstance*) node->GetInstance(in))->FindSkeletonNodes(roots); -#endif - 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) { +void DAEToEggConverter:: +process_node(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(FROM_FSTRING(node->GetName())); + PT(EggGroup) node_group = new EggGroup(FROM_FSTRING(node->GetDaeId())); process_extra(node_group, node->GetExtra()); parent->add_child(node_group); + // Check if its a joint if (node->IsJoint()) { + string sid = FROM_FSTRING(node->GetSubId()); node_group->set_group_type(EggGroup::GT_joint); - _joints[node_id] = node_group; + + if (!_joints.insert(DaeCharacter::JointMap::value_type(sid, + DaeCharacter::Joint(node_group, node))).second) { + daeegg_cat.error() + << "Joint with sid " << sid << " occurs more than once!\n"; + } } - // 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 transforms and apply them (in reverse order) + for (size_t tr = node->GetTransformCount(); tr > 0; --tr) { + apply_transform(node_group, node->GetTransform(tr - 1)); } + //node_group->set_transform3d(convert_matrix(node->ToMatrix())); + // 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()); + const FCDEntity *entity = node->GetInstance(in)->GetEntity(); + if (entity && entity->GetType() == FCDEntity::SCENE_NODE) { + process_node(node_group, (const FCDSceneNode*) entity); } } } -void DAEToEggConverter::process_instance(PT(EggGroup) parent, const FCDEntityInstance* instance) { +void DAEToEggConverter:: +process_instance(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)); + case FCDEntityInstance::GEOMETRY: + { + if (get_animation_convert() != AC_chan) { + 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->GetName()), const_cast (geometry->GetSpline())); + } } - if (geometry->IsSpline()) { - process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast (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. + } + 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 its 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; + } + 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) { +void DAEToEggConverter:: +process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh, + DaeMaterials *materials, DaeCharacter *character) { + nassertv(mesh != NULL); daeegg_cat.debug() << "Processing mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << endl; - + // 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) { daeegg_cat.debug() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has no sources" << endl; return; } - const FCDGeometrySource* vsource = mesh->FindSourceByType(FUDaeGeometryInput::POSITION); + const FCDGeometrySource* vsource = mesh->FindSourceByType(FUDaeGeometryInput::POSITION); if (vsource == NULL) { daeegg_cat.debug() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has no source for POSITION data" << endl; return; } - + // Loop through the polygon groups and add them daeegg_cat.spam() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has " << mesh->GetPolygonsCount() << " polygon groups" << endl; if (mesh->GetPolygonsCount() == 0) return; - + // This is an array of pointers, I know. But since they are refcounted, I don't have a better idea. PT(EggGroup) *primitive_holders = new PT(EggGroup) [mesh->GetPolygonsCount()]; for (size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) { const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr); + string material_semantic = FROM_FSTRING(polygons->GetMaterialSemantic()); + // Stores which group holds the primitives. PT(EggGroup) primitiveholder; // 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())); + //primitiveholder = new EggGroup(FROM_FSTRING(mesh->GetDaeId()) + "." + material_semantic); + primitiveholder = new EggGroup; mesh_group->add_child(primitiveholder); } else { primitiveholder = mesh_group; @@ -357,7 +529,7 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* primitive_holders[gr] = primitiveholder; // Apply the per-group data of the materials, if we have it. if (materials != NULL) { - materials->apply_to_group(FROM_FSTRING(polygons->GetMaterialSemantic()), primitiveholder, _invert_transparency); + materials->apply_to_group(material_semantic, primitiveholder, _invert_transparency); } // Find the position sources const FCDGeometryPolygonsInput* pinput = polygons->FindInput(FUDaeGeometryInput::POSITION); @@ -389,26 +561,47 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* const uint32* tindices; if (tinput != NULL) tindices = tinput->GetIndices(); // Get a name for potential coordinate sets - string tcsetname (""); + string tcsetname; if (materials != NULL && tcinput != NULL) { - daeegg_cat.debug() << "Assigning texcoord set " << tcinput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n"; - tcsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXCOORD, tcinput->GetSet()); + if (daeegg_cat.is_debug()) { + daeegg_cat.debug() + << "Assigning texcoord set " << tcinput->GetSet() + << " to semantic '" << material_semantic << "'\n"; + } + tcsetname = materials->get_uvset_name(material_semantic, + FUDaeGeometryInput::TEXCOORD, tcinput->GetSet()); } - string tbsetname (""); + string tbsetname; if (materials != NULL && binput != NULL) { - daeegg_cat.debug() << "Assigning texbinormal set " << binput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n"; - tbsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXBINORMAL, binput->GetSet()); + if (daeegg_cat.is_debug()) { + daeegg_cat.debug() + << "Assigning texbinormal set " << binput->GetSet() + << " to semantic '" << material_semantic << "'\n"; + } + tbsetname = materials->get_uvset_name(material_semantic, + FUDaeGeometryInput::TEXBINORMAL, binput->GetSet()); } - string ttsetname (""); + string ttsetname; if (materials != NULL && tinput != NULL) { - daeegg_cat.debug() << "Assigning textangent set " << tinput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n"; - ttsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXTANGENT, tinput->GetSet()); + if (daeegg_cat.is_debug()) { + daeegg_cat.debug() + << "Assigning textangent set " << tinput->GetSet() + << " to semantic '" << material_semantic << "'\n"; + } + ttsetname = materials->get_uvset_name(material_semantic, + FUDaeGeometryInput::TEXTANGENT, tinput->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])); + + if (character != NULL) { + // If this is skinned geometry, add the vertex influences. + character->influence_vertex(indices[ix], vertex); + } + // Process the normal if (nsource != NULL && ninput != NULL) { assert(nsource->GetStride() == 3); @@ -469,26 +662,26 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* 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!" << endl; + 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!" << endl; } if (primitive != NULL) { primitive_holders[gr]->add_child(primitive); @@ -506,7 +699,8 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* delete[] primitive_holders; } -void DAEToEggConverter::process_spline(PT(EggGroup) parent, const string group_name, FCDGeometrySpline* geometry_spline) { +void DAEToEggConverter:: +process_spline(EggGroup *parent, const string group_name, FCDGeometrySpline* geometry_spline) { assert(geometry_spline != NULL); PT(EggGroup) result = new EggGroup(group_name); parent->add_child(result); @@ -521,7 +715,8 @@ void DAEToEggConverter::process_spline(PT(EggGroup) parent, const string group_n } } -void DAEToEggConverter::process_spline(PT(EggGroup) parent, const FCDSpline* spline) { +void DAEToEggConverter:: +process_spline(EggGroup *parent, const FCDSpline* spline) { assert(spline != NULL); nassertv(spline->GetSplineType() == FUDaeSplineType::NURBS); // Now load in the nurbs curve to the egg library @@ -542,70 +737,26 @@ void DAEToEggConverter::process_spline(PT(EggGroup) parent, const FCDSpline* spl } } -void DAEToEggConverter::process_controller(PT(EggGroup) parent, const FCDControllerInstance* instance) { +void DAEToEggConverter:: +process_controller(EggGroup *parent, const FCDControllerInstance *instance) { assert(instance != NULL); - const FCDController* controller = (const FCDController*) instance->GetEntity(); + 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 (get_animation_convert() == AC_none) { + // If we're exporting a static mesh, export the base geometry as-is. + const FCDGeometryMesh *mesh = controller->GetBaseGeometry()->GetMesh(); + if (mesh != NULL) { + PT(DaeMaterials) materials = new DaeMaterials(instance); daeegg_cat.spam() << "Processing mesh for controller\n"; - if (_vertex_pools.count(FROM_FSTRING(geometry->GetMesh()->GetDaeId()))) { - daeegg_cat.debug() << "Using vertex pool " << FROM_FSTRING(geometry->GetMesh()->GetDaeId()) << "\n"; - vertex_pool = _vertex_pools[FROM_FSTRING(geometry->GetMesh()->GetDaeId())]; - } - } - if (geometry->IsSpline()) { - process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast (geometry->GetSpline())); - } - } - // Add the joint hierarchy -#if FCOLLADA_VERSION < 0x00030005 - FCDSceneNodeList roots = (const_cast (instance))->FindSkeletonNodes(); -#else - FCDSceneNodeList roots; - (const_cast (instance))->FindSkeletonNodes(roots); -#endif - 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 > > 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 (vertex_pool->get_vertex(in), jwpair->weight)); - } - } - } - // Loop through the joints in the vertex influences - for (pmap > >::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 >::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; - } - } + process_mesh(parent, mesh, materials); } + } else { + // Add a character for this to the table, the mesh is processed later + PT(DaeCharacter) character = new DaeCharacter(parent, instance); + _characters.push_back(character); } + if (controller->IsMorph()) { assert(controller != NULL); const FCDMorphController* morph_controller = controller->GetMorphController(); @@ -628,28 +779,25 @@ void DAEToEggConverter::process_controller(PT(EggGroup) parent, const FCDControl morph->add_child(target); } } - - // Get a 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()); } -void DAEToEggConverter::process_extra(PT(EggGroup) group, const FCDExtra* extra) { +void DAEToEggConverter:: +process_extra(EggGroup *group, const FCDExtra* extra) { if (extra == NULL) { return; } nassertv(group != NULL); - + const FCDEType* etype = extra->GetDefaultType(); if (etype == NULL) { return; } - + const FCDENode* enode = (const FCDENode*) etype->FindTechnique("PANDA3D"); if (enode == NULL) { return; } - + FCDENodeList tags; enode->FindChildrenNodes("param", tags); for (FCDENodeList::iterator it = tags.begin(); it != tags.end(); ++it) { @@ -660,18 +808,45 @@ void DAEToEggConverter::process_extra(PT(EggGroup) group, const FCDExtra* extra) } } -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; +LMatrix4d DAEToEggConverter:: +convert_matrix(const FMMatrix44 &matrix) { + return LMatrix4d( + matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3], + matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3], + matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3], + matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]); } -void DAEToEggConverter::apply_transform(const PT(EggGroup) to, const FCDTransform* from) { +void DAEToEggConverter:: +apply_transform(EggGroup *to, const FCDTransform* from) { assert(from != NULL); assert(to != NULL); - to->set_transform3d(convert_matrix(from->ToMatrix()) * to->get_transform3d()); + //to->set_transform3d(convert_matrix(from->ToMatrix()) * to->get_transform3d()); + switch (from->GetType()) { + case FCDTransform::TRANSLATION: + { + const FCDTTranslation *trans = (const FCDTTranslation *)from; + to->add_translate3d(TO_VEC3(trans->GetTranslation())); + } + break; + + case FCDTransform::ROTATION: + { + const FCDTRotation *rot = (const FCDTRotation *)from; + to->add_rotate3d(rot->GetAngle(), TO_VEC3(rot->GetAxis())); + } + break; + + case FCDTransform::SCALE: + { + const FCDTScale *scale = (const FCDTScale *)from; + to->add_scale3d(TO_VEC3(scale->GetScale())); + } + break; + + default: + // Either a matrix, or something we can't handle. + to->add_matrix4(convert_matrix(from->ToMatrix())); + break; + } } diff --git a/pandatool/src/daeegg/daeToEggConverter.h b/pandatool/src/daeegg/daeToEggConverter.h index f3384e93ee..e2c29a1fa1 100755 --- a/pandatool/src/daeegg/daeToEggConverter.h +++ b/pandatool/src/daeegg/daeToEggConverter.h @@ -35,6 +35,7 @@ #include "FMath/FMMatrix44.h" #include "daeMaterials.h" +#include "daeCharacter.h" #include "pvector.h" // Include last //////////////////////////////////////////////////////////////////// @@ -47,39 +48,41 @@ 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); + virtual DistanceUnit get_input_units(); bool _invert_transparency; private: + string _unit_name; + double _unit_meters; PT(EggTable) _table; FCDocument* _document; FUErrorSimpleHandler* _error_handler; - pmap _joints; - pmap _vertex_pools; - pvector _skeletons; - int _frame_rate; - + DaeCharacter::JointMap _joints; + + typedef pvector Characters; + Characters _characters; + 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); - void process_extra(PT(EggGroup) group, const FCDExtra* extra); - + void process_node(EggGroupNode *parent, const FCDSceneNode* node, bool forced = false); + void process_instance(EggGroup *parent, const FCDEntityInstance* instance); + void process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh, + DaeMaterials *materials, DaeCharacter *character = NULL); + void process_spline(EggGroup *parent, const string group_name, FCDGeometrySpline* geometry_spline); + void process_spline(EggGroup *parent, const FCDSpline* spline); + void process_controller(EggGroup *parent, const FCDControllerInstance* instance); + void process_extra(EggGroup *group, const FCDExtra* extra); + static LMatrix4d convert_matrix(const FMMatrix44& matrix); - void apply_transform(const PT(EggGroup) to, const FCDTransform* from); - + void apply_transform(EggGroup *to, const FCDTransform* from); + friend class DaeCharacter; }; diff --git a/pandatool/src/daeprogs/daeToEgg.cxx b/pandatool/src/daeprogs/daeToEgg.cxx index 503d1af33a..38a0eb9cdb 100755 --- a/pandatool/src/daeprogs/daeToEgg.cxx +++ b/pandatool/src/daeprogs/daeToEgg.cxx @@ -26,6 +26,7 @@ DAEToEgg:: DAEToEgg(): SomethingToEgg("COLLADA", ".dae") { + add_animation_options(); add_units_options(); add_normals_options(); add_transform_options(); @@ -42,6 +43,7 @@ DAEToEgg(): ("This program converts .dae files (COLLADA Digital Asset Exchange) to .egg."); _coordinate_system = CS_yup_right; + _animation_convert = AC_both; } //////////////////////////////////////////////////////////////////// @@ -51,6 +53,12 @@ DAEToEgg(): //////////////////////////////////////////////////////////////////// void DAEToEgg:: run() { + if (_animation_convert != AC_both && _animation_convert != AC_none && + _animation_convert != AC_chan && _animation_convert != AC_model) { + cerr << "Unsupported animation convert option.\n"; + exit(1); + } + nout << "Reading " << _input_filename << "\n"; _data->set_coordinate_system(_coordinate_system); From c0e4de3df70f6ae19f660e4791c258d37e7f4adb Mon Sep 17 00:00:00 2001 From: 09th Date: Tue, 24 Feb 2015 19:58:14 +0100 Subject: [PATCH 10/20] Fix bam2egg issue with animated models --- panda/src/egg2pg/eggSaver.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/egg2pg/eggSaver.cxx b/panda/src/egg2pg/eggSaver.cxx index 83f0d2aaeb..8086b33aaf 100755 --- a/panda/src/egg2pg/eggSaver.cxx +++ b/panda/src/egg2pg/eggSaver.cxx @@ -347,7 +347,7 @@ convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, Charac CharacterJoint *character_joint = DCAST(CharacterJoint, bundleNode); LMatrix4 transformf; - character_joint->get_net_transform(transformf); + character_joint->get_transform(transformf); LMatrix4d transformd(LCAST(double, transformf)); EggGroup *joint = new EggGroup(bundleNode->get_name()); joint->add_matrix4(transformd); From 46ddd46c5cee7181884dc5541b591474a5714c37 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 24 Feb 2015 21:40:55 +0100 Subject: [PATCH 11/20] Support materials in bam2egg --- panda/src/egg2pg/eggSaver.cxx | 49 ++++++++++++++++++++++++++++++++++- panda/src/egg2pg/eggSaver.h | 3 ++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/panda/src/egg2pg/eggSaver.cxx b/panda/src/egg2pg/eggSaver.cxx index 8086b33aaf..051c3b6f54 100755 --- a/panda/src/egg2pg/eggSaver.cxx +++ b/panda/src/egg2pg/eggSaver.cxx @@ -22,6 +22,7 @@ #include "transformState.h" #include "colorScaleAttrib.h" #include "colorAttrib.h" +#include "materialAttrib.h" #include "textureAttrib.h" #include "cullFaceAttrib.h" #include "transparencyAttrib.h" @@ -577,6 +578,13 @@ convert_primitive(const GeomVertexData *vertex_data, } } + // Check for a material. + EggMaterial *egg_mat = (EggMaterial *)NULL; + const MaterialAttrib *ma = DCAST(MaterialAttrib, net_state->get_attrib(MaterialAttrib::get_class_type())); + if (ma != (const MaterialAttrib *)NULL) { + egg_mat = get_egg_material(ma->get_material()); + } + // Check for a texture. EggTexture *egg_tex = (EggTexture *)NULL; const TextureAttrib *ta = DCAST(TextureAttrib, net_state->get_attrib(TextureAttrib::get_class_type())); @@ -703,11 +711,15 @@ convert_primitive(const GeomVertexData *vertex_data, // Huh, an unknown geometry type. return; } - + for (int i = 0; i < num_primitives; ++i) { PT(EggPrimitive) egg_prim = (*make_func)(); egg_parent->add_child(egg_prim); + + if (egg_mat != (EggMaterial *)NULL) { + egg_prim->set_material(egg_mat); + } if (egg_tex != (EggTexture *)NULL) { egg_prim->set_texture(egg_tex); } @@ -947,6 +959,41 @@ apply_tag(EggGroup *egg_group, PandaNode *node, const string &tag) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: EggSaver::get_egg_material +// Access: Private +// Description: Returns an EggMaterial pointer that corresponds to +// the indicated Material. +//////////////////////////////////////////////////////////////////// +EggMaterial *EggSaver:: +get_egg_material(Material *mat) { + if (mat != (Material *)NULL) { + EggMaterial temp(mat->get_name()); + if (mat->has_ambient()) { + temp.set_amb(mat->get_ambient()); + } + + if (mat->has_diffuse()) { + temp.set_diff(mat->get_diffuse()); + } + + if (mat->has_specular()) { + temp.set_spec(mat->get_specular()); + } + + if (mat->has_emission()) { + temp.set_emit(mat->get_emission()); + } + + temp.set_shininess(mat->get_shininess()); + temp.set_local(mat->get_local()); + + return _materials.create_unique_material(temp, ~EggMaterial::E_mref_name); + } + + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: EggSaver::get_egg_texture // Access: Private diff --git a/panda/src/egg2pg/eggSaver.h b/panda/src/egg2pg/eggSaver.h index c565b258af..0dfbdc8838 100755 --- a/panda/src/egg2pg/eggSaver.h +++ b/panda/src/egg2pg/eggSaver.h @@ -92,6 +92,7 @@ private: bool apply_tags(EggGroup *egg_group, PandaNode *node); bool apply_tag(EggGroup *egg_group, PandaNode *node, const string &tag); + EggMaterial *get_egg_material(Material *tex); EggTexture *get_egg_texture(Texture *tex); static EggPrimitive *make_egg_polygon(); @@ -102,8 +103,8 @@ private: PT(EggData) _data; PT(EggVertexPool) _vpool; - EggTextureCollection _textures; EggMaterialCollection _materials; + EggTextureCollection _textures; }; #include "eggSaver.I" From 8dbe681143f7e658ed257dc25a67bdf4dbdc9e3d Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 24 Feb 2015 23:51:00 +0100 Subject: [PATCH 12/20] Fix bug with Collide flag "polyset" and nested elements --- panda/src/collide/collisionBox.cxx | 16 +++++++----- panda/src/egg2pg/eggLoader.cxx | 41 ++++++++++++++---------------- panda/src/pgraph/polylightNode.I | 5 ++-- panda/src/pgraph/polylightNode.cxx | 24 +++++++++++++++++ panda/src/pgraph/polylightNode.h | 8 +++--- 5 files changed, 59 insertions(+), 35 deletions(-) diff --git a/panda/src/collide/collisionBox.cxx b/panda/src/collide/collisionBox.cxx index f467d73a8b..e1bdf03970 100644 --- a/panda/src/collide/collisionBox.cxx +++ b/panda/src/collide/collisionBox.cxx @@ -144,15 +144,19 @@ test_intersection(const CollisionEntry &entry) const { //////////////////////////////////////////////////////////////////// void CollisionBox:: xform(const LMatrix4 &mat) { + _min = _min * mat; + _max = _max * mat; _center = _center * mat; - for(int v = 0; v < 8; v++) + for(int v = 0; v < 8; v++) { _vertex[v] = _vertex[v] * mat; - for(int p = 0; p < 6 ; p++) + } + for(int p = 0; p < 6 ; p++) { _planes[p] = set_plane(p); - _x = _vertex[0].get_x()-_center.get_x(); - _y = _vertex[0].get_y()-_center.get_y(); - _z = _vertex[0].get_z()-_center.get_z(); - _radius = sqrt( _x*_x + _y*_y + _z*_z ); + } + _x = _vertex[0].get_x() - _center.get_x(); + _y = _vertex[0].get_y() - _center.get_y(); + _z = _vertex[0].get_z() - _center.get_z(); + _radius = sqrt(_x * _x + _y * _y + _z * _z); setup_box(); mark_viz_stale(); mark_internal_bounds_stale(); diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 8cafc8dced..ae3be83199 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1865,6 +1865,10 @@ make_node(EggGroup *egg_group, PandaNode *parent) { node = new CollisionNode(egg_group->get_name()); make_collision_solids(egg_group, egg_group, (CollisionNode *)node.p()); + + // Transform all of the collision solids into local space. + node->xform(LCAST(PN_stdfloat, egg_group->get_vertex_to_node())); + if ((egg_group->get_collide_flags() & EggGroup::CF_keep) != 0) { // If we also specified to keep the geometry, continue the // traversal. In this case, we create a new PandaNode to be the @@ -1925,8 +1929,11 @@ make_node(EggGroup *egg_group, PandaNode *parent) { pnode->set_pos(center); pnode->set_color(color); pnode->set_radius(radius); + + pnode->xform(LCAST(PN_stdfloat, egg_group->get_vertex_to_node())); + node = pnode; - + } else if (egg_group->get_switch_flag()) { if (egg_group->get_switch_fps() != 0.0) { // Create a sequence node. @@ -2790,7 +2797,6 @@ find_first_polygon(EggGroup *egg_group) { bool EggLoader:: make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, LPoint3 ¢er, PN_stdfloat &radius, LColor &color) { - bool success=false; EggGroup *geom_group = find_collision_geometry(egg_group, flags); if (geom_group != (EggGroup *)NULL) { // Collect all of the vertices. @@ -2822,15 +2828,12 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, d_center /= (double)num_vertices; //egg2pg_cat.debug() << "make_sphere d_center: " << d_center << "\n"; - LMatrix4d mat = egg_group->get_vertex_to_node(); - d_center = d_center * mat; - // And the furthest vertex determines the radius. double radius2 = 0.0; for (vi = vertices.begin(); vi != vertices.end(); ++vi) { EggVertex *vtx = (*vi); LPoint3d p3 = vtx->get_pos3(); - LVector3d v = p3 * mat - d_center; + LVector3d v = p3 - d_center; radius2 = max(radius2, v.length_squared()); } @@ -2841,10 +2844,10 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, vi = vertices.begin(); EggVertex *clr_vtx = (*vi); color = clr_vtx->get_color(); - success = true; + return true; } } - return success; + return false; } //////////////////////////////////////////////////////////////////// @@ -2900,9 +2903,8 @@ make_box(EggGroup *egg_group, EggGroup::CollideFlags flags, max(max_pd[2], pos[2])); } - LMatrix4d mat = egg_group->get_vertex_to_node(); - min_p = LCAST(PN_stdfloat, min_pd * mat); - max_p = LCAST(PN_stdfloat, max_pd * mat); + min_p = LCAST(PN_stdfloat, min_pd); + max_p = LCAST(PN_stdfloat, max_pd); return (min_pd != max_pd); } return false; @@ -3170,7 +3172,6 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode, // also determine the centroid). We compute this in node space. size_t num_vertices = vertices.size(); if (num_vertices != 0) { - LMatrix4d mat = egg_group->get_vertex_to_node(); pvector vpos; vpos.reserve(num_vertices); @@ -3178,7 +3179,7 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode, pset::const_iterator vi; for (vi = vertices.begin(); vi != vertices.end(); ++vi) { EggVertex *vtx = (*vi); - LPoint3d pos = vtx->get_pos3() * mat; + const LPoint3d &pos = vtx->get_pos3(); vpos.push_back(pos); center += pos; } @@ -3420,20 +3421,18 @@ create_collision_plane(EggPolygon *egg_poly, EggGroup *parent_group) { << "\n"; } - LMatrix4d mat = egg_poly->get_vertex_to_node(); - pvector vertices; if (!egg_poly->empty()) { EggPolygon::const_iterator vi; vi = egg_poly->begin(); - LVertexd vert = (*vi)->get_pos3() * mat; + LVertexd vert = (*vi)->get_pos3(); vertices.push_back(LCAST(PN_stdfloat, vert)); LVertexd last_vert = vert; ++vi; while (vi != egg_poly->end()) { - vert = (*vi)->get_pos3() * mat; + vert = (*vi)->get_pos3(); if (!vert.almost_equal(last_vert)) { vertices.push_back(LCAST(PN_stdfloat, vert)); } @@ -3461,7 +3460,6 @@ void EggLoader:: create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly, EggGroup *parent_group, EggGroup::CollideFlags flags) { - LMatrix4d mat = egg_poly->get_vertex_to_node(); PT(EggGroup) group = new EggGroup; @@ -3489,13 +3487,13 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly, EggPolygon::const_iterator vi; vi = poly->begin(); - LVertexd vert = (*vi)->get_pos3() * mat; + LVertexd vert = (*vi)->get_pos3(); vertices.push_back(LCAST(PN_stdfloat, vert)); LVertexd last_vert = vert; ++vi; while (vi != poly->end()) { - vert = (*vi)->get_pos3() * mat; + vert = (*vi)->get_pos3(); if (!vert.almost_equal(last_vert)) { vertices.push_back(LCAST(PN_stdfloat, vert)); } @@ -3513,12 +3511,11 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly, if (cspoly->is_valid()) { apply_collision_flags(cspoly, flags); cnode->add_solid(cspoly); - } + } } } } - //////////////////////////////////////////////////////////////////// // Function: EggLoader::create_collision_floor_mesh // Access: Private diff --git a/panda/src/pgraph/polylightNode.I b/panda/src/pgraph/polylightNode.I index 4571035db7..c9b7de7c6d 100755 --- a/panda/src/pgraph/polylightNode.I +++ b/panda/src/pgraph/polylightNode.I @@ -85,11 +85,10 @@ disable(){ // Description: Set this light's position //////////////////////////////////////////////////////////////////// INLINE void PolylightNode:: -set_pos(const LVecBase3 &position){ +set_pos(const LPoint3 &position) { _position = position; } - //////////////////////////////////////////////////////////////////// // Function: PolylightNode::set_pos // Access: Published @@ -107,7 +106,7 @@ set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z){ // Access: Published // Description: Returns position as a LPoint3 //////////////////////////////////////////////////////////////////// -INLINE LVecBase3 PolylightNode:: +INLINE LPoint3 PolylightNode:: get_pos() const { return _position; } diff --git a/panda/src/pgraph/polylightNode.cxx b/panda/src/pgraph/polylightNode.cxx index 1d2c87693c..8d383db018 100755 --- a/panda/src/pgraph/polylightNode.cxx +++ b/panda/src/pgraph/polylightNode.cxx @@ -65,6 +65,30 @@ make_copy() const { return new PolylightNode(*this); } +//////////////////////////////////////////////////////////////////// +// Function: PolylightNode::xform +// Access: Public, Virtual +// Description: Transforms the contents of this node by the indicated +// matrix, if it means anything to do so. For most +// kinds of nodes, this does nothing. +//////////////////////////////////////////////////////////////////// +void PolylightNode:: +xform(const LMatrix4 &mat) { + nassertv(!mat.is_nan()); + + if (mat.almost_equal(LMatrix4::ident_mat())) { + return; + } + + _position = _position * mat; + + // This is a little cheesy and fails miserably in the presence of a + // non-uniform scale. + LVector3 radius_v = LVector3(_radius, 0.0f, 0.0f) * mat; + _radius = length(radius_v); + mark_internal_bounds_stale(); +} + //////////////////////////////////////////////////////////////////// // Function: PolylightNode::Constructor // Access: Public diff --git a/panda/src/pgraph/polylightNode.h b/panda/src/pgraph/polylightNode.h index 8eb3aacbee..caacbecf57 100755 --- a/panda/src/pgraph/polylightNode.h +++ b/panda/src/pgraph/polylightNode.h @@ -58,9 +58,9 @@ PUBLISHED: PolylightNode(const string &name); INLINE void enable(); INLINE void disable(); - INLINE void set_pos(const LVecBase3 &position); + INLINE void set_pos(const LPoint3 &position); INLINE void set_pos(PN_stdfloat x,PN_stdfloat y, PN_stdfloat z); - INLINE LVecBase3 get_pos() const; + INLINE LPoint3 get_pos() const; INLINE void set_color(const LColor &color); INLINE void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b); INLINE LColor get_color() const; @@ -100,11 +100,11 @@ PUBLISHED: public: LColor flicker() const; virtual PandaNode *make_copy() const; + virtual void xform(const LMatrix4 &mat); - private: bool _enabled; - LVecBase3 _position; + LPoint3 _position; LColor _color; PN_stdfloat _radius; Attenuation_Type _attenuation_type; From 894423ace4961ac6abc53512a8e05f9c2b5e85b7 Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Tue, 24 Feb 2015 16:06:40 -0800 Subject: [PATCH 13/20] ffmpeg: Don't use internal SWR_CH_MAX macro. --- panda/src/ffmpeg/ffmpegAudioCursor.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index 5cddb016c8..4eab28e4b6 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -313,8 +313,7 @@ reload_buffer() { #ifdef HAVE_SWRESAMPLE if (_resample_ctx) { // Resample the data to signed 16-bit sample format. - uint8_t* out[SWR_CH_MAX] = {(uint8_t*) _buffer, NULL}; - bufsize = swr_convert(_resample_ctx, out, _buffer_size / 2, (const uint8_t**)_frame->extended_data, _frame->nb_samples); + bufsize = swr_convert(_resample_ctx, (uint8_t **)&_buffer, _buffer_size / 2, (const uint8_t**)_frame->extended_data, _frame->nb_samples); bufsize *= _audio_channels * 2; } else #endif From 903966371c861a3084174103fa3407bc2f6bbad9 Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Tue, 24 Feb 2015 15:41:05 -0800 Subject: [PATCH 14/20] general: Fix missing includes. --- panda/src/gobj/samplerContext.h | 1 + panda/src/gobj/samplerState.h | 1 + panda/src/pgraph/cullBinManager.h | 1 + panda/src/pgraph/shaderPool.cxx | 1 + 4 files changed, 4 insertions(+) diff --git a/panda/src/gobj/samplerContext.h b/panda/src/gobj/samplerContext.h index 61a876d405..a51157ccc0 100644 --- a/panda/src/gobj/samplerContext.h +++ b/panda/src/gobj/samplerContext.h @@ -18,6 +18,7 @@ #include "pandabase.h" #include "adaptiveLru.h" +#include "simpleLru.h" #include "samplerState.h" #include "savedContext.h" diff --git a/panda/src/gobj/samplerState.h b/panda/src/gobj/samplerState.h index d5c10d6a1c..de3e4d6cf5 100644 --- a/panda/src/gobj/samplerState.h +++ b/panda/src/gobj/samplerState.h @@ -21,6 +21,7 @@ #include "namable.h" #include "luse.h" #include "numeric_types.h" +#include "bamReader.h" #include "config_gobj.h" class FactoryParams; diff --git a/panda/src/pgraph/cullBinManager.h b/panda/src/pgraph/cullBinManager.h index 4e6adf0821..6d29d9e1f4 100644 --- a/panda/src/pgraph/cullBinManager.h +++ b/panda/src/pgraph/cullBinManager.h @@ -20,6 +20,7 @@ #include "cullBinEnums.h" #include "pointerTo.h" #include "pvector.h" +#include "epvector.h" #include "pmap.h" #include "vector_int.h" #include "pStatCollector.h" diff --git a/panda/src/pgraph/shaderPool.cxx b/panda/src/pgraph/shaderPool.cxx index 1ca9ddbe00..5476960c6e 100644 --- a/panda/src/pgraph/shaderPool.cxx +++ b/panda/src/pgraph/shaderPool.cxx @@ -18,6 +18,7 @@ #include "virtualFileSystem.h" #include "loader.h" #include "shader.h" +#include "string_utils.h" ShaderPool *ShaderPool::_global_ptr = (ShaderPool *)NULL; From f0b3e08e9c75e5cdcd98c0f3142469918d1d2fd5 Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Tue, 24 Feb 2015 16:22:37 -0800 Subject: [PATCH 15/20] ffmpeg: Use av_frame_* instead of deprecated avcodec_*_frame functions beginning with lavc 55.45.101. --- panda/src/ffmpeg/ffmpegAudioCursor.cxx | 8 +++++++- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index 4eab28e4b6..a33db26b6f 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -148,7 +148,11 @@ FfmpegAudioCursor(FfmpegAudio *src) : _can_seek = true; _can_seek_fast = true; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100) + _frame = av_frame_alloc(); +#else _frame = avcodec_alloc_frame(); +#endif _packet = new AVPacket; _buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE / 2; @@ -194,7 +198,9 @@ FfmpegAudioCursor:: void FfmpegAudioCursor:: cleanup() { if (_frame) { -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100) +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 45, 101) + av_frame_free(&_frame); +#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100) avcodec_free_frame(&_frame); #else av_free(&_frame); diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index a02dac184b..87b3b48395 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -94,8 +94,13 @@ init_from(FfmpegVideo *source) { PIX_FMT_BGR24, SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL); #endif // HAVE_SWSCALE +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100) + _frame = av_frame_alloc(); + _frame_out = av_frame_alloc(); +#else _frame = avcodec_alloc_frame(); _frame_out = avcodec_alloc_frame(); +#endif if ((_frame == 0)||(_frame_out == 0)) { cleanup(); From 7a6aa7bfae8704d598146241a00ed0b36bfd9ca5 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 25 Feb 2015 01:25:19 +0100 Subject: [PATCH 16/20] Implement ParamNodePath; fix circular include issue in shaderInput.h --- panda/src/pgraph/Sources.pp | 3 + panda/src/pgraph/config_pgraph.cxx | 2 + panda/src/pgraph/nodePath.h | 4 +- panda/src/pgraph/p3pgraph_composite3.cxx | 1 + panda/src/pgraph/paramNodePath.I | 60 +++++++++++++ panda/src/pgraph/paramNodePath.cxx | 108 +++++++++++++++++++++++ panda/src/pgraph/paramNodePath.h | 75 ++++++++++++++++ panda/src/pgraph/shaderInput.I | 27 ------ panda/src/pgraph/shaderInput.cxx | 32 ++++++- panda/src/pgraph/shaderInput.h | 8 +- 10 files changed, 284 insertions(+), 36 deletions(-) create mode 100644 panda/src/pgraph/paramNodePath.I create mode 100644 panda/src/pgraph/paramNodePath.cxx create mode 100644 panda/src/pgraph/paramNodePath.h diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 51e0bdb0fa..838adc49b4 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -79,6 +79,7 @@ occluderNode.I occluderNode.h \ pandaNode.I pandaNode.h \ pandaNodeChain.I pandaNodeChain.h \ + paramNodePath.I paramNodePath.h \ planeNode.I planeNode.h \ polylightEffect.I polylightEffect.h \ polylightNode.I polylightNode.h \ @@ -184,6 +185,7 @@ occluderNode.cxx \ pandaNode.cxx \ pandaNodeChain.cxx \ + paramNodePath.cxx \ planeNode.cxx \ polylightEffect.cxx \ polylightNode.cxx \ @@ -286,6 +288,7 @@ pandaNode.I pandaNode.h \ pandaNode_ext.h pandaNode_ext.cxx \ pandaNodeChain.I pandaNodeChain.h \ + paramNodePath.I paramNodePath.h \ planeNode.I planeNode.h \ polylightEffect.I polylightEffect.h \ polylightNode.I polylightNode.h \ diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 18b85ea77c..a79eb0c23d 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -60,6 +60,7 @@ #include "nodePath.h" #include "nodePathComponent.h" #include "pandaNode.h" +#include "paramNodePath.h" #include "planeNode.h" #include "polylightEffect.h" #include "polylightNode.h" @@ -436,6 +437,7 @@ init_libpgraph() { NodePathComponent::init_type(); PandaNode::init_type(); PandaNodePipelineReader::init_type(); + ParamNodePath::init_type(); PlaneNode::init_type(); PolylightNode::init_type(); PolylightEffect::init_type(); diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index f03580f255..d84519547d 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -38,6 +38,7 @@ #include "pta_LVecBase3.h" #include "pta_LVecBase2.h" #include "stl_compares.h" +#include "shaderInput.h" class NodePathCollection; class FindApproxPath; @@ -1008,9 +1009,6 @@ private: INLINE ostream &operator << (ostream &out, const NodePath &node_path); -// We have to put this down here, to work around a circular include. -#include "shaderInput.h" - #include "nodePath.I" #endif diff --git a/panda/src/pgraph/p3pgraph_composite3.cxx b/panda/src/pgraph/p3pgraph_composite3.cxx index b539fefcee..5b88a55d2f 100644 --- a/panda/src/pgraph/p3pgraph_composite3.cxx +++ b/panda/src/pgraph/p3pgraph_composite3.cxx @@ -21,6 +21,7 @@ #include "occluderNode.cxx" #include "pandaNode.cxx" #include "pandaNodeChain.cxx" +#include "paramNodePath.cxx" #include "planeNode.cxx" #include "polylightEffect.cxx" #include "polylightNode.cxx" diff --git a/panda/src/pgraph/paramNodePath.I b/panda/src/pgraph/paramNodePath.I new file mode 100644 index 0000000000..8d52ac5ad6 --- /dev/null +++ b/panda/src/pgraph/paramNodePath.I @@ -0,0 +1,60 @@ +// Filename: paramNodePath.I +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::Constructor +// Access: Published +// Description: Creates a new ParamNodePath storing the given +// node path object. +//////////////////////////////////////////////////////////////////// +INLINE ParamNodePath:: +ParamNodePath(const NodePath &node_path) : + _node_path(node_path) +{ +} + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::Move Constructor +// Access: Published +// Description: Creates a new ParamNodePath storing the given +// node path object. +//////////////////////////////////////////////////////////////////// +INLINE ParamNodePath:: +ParamNodePath(NodePath &&node_path) NOEXCEPT : + _node_path(move(node_path)) +{ +} +#endif // USE_MOVE_SEMANTICS + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::get_value_type +// Access: Published, Virtual +// Description: Returns NodePath::get_class_type(). +//////////////////////////////////////////////////////////////////// +INLINE TypeHandle ParamNodePath:: +get_value_type() const { + return NodePath::get_class_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::get_value +// Access: Published +// Description: Retrieves the NodePath stored in the parameter. +//////////////////////////////////////////////////////////////////// +INLINE const NodePath &ParamNodePath:: +get_value() const { + return _node_path; +} diff --git a/panda/src/pgraph/paramNodePath.cxx b/panda/src/pgraph/paramNodePath.cxx new file mode 100644 index 0000000000..00fb5be24a --- /dev/null +++ b/panda/src/pgraph/paramNodePath.cxx @@ -0,0 +1,108 @@ +// Filename: paramNodePath.cxx +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "paramNodePath.h" +#include "dcast.h" +#include "pandaNode.h" + +TypeHandle ParamNodePath::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void ParamNodePath:: +output(ostream &out) const { + out << "node path " << _node_path; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// ParamValue. +//////////////////////////////////////////////////////////////////// +void ParamNodePath:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void ParamNodePath:: +write_datagram(BamWriter *manager, Datagram &dg) { + ParamValueBase::write_datagram(manager, dg); + + // We can't store a NodePath, so we store a pointer to the + // underlying node, and pray that there is an unambiguous path + // from the root to it. + if (_node_path.is_empty()) { + manager->write_pointer(dg, NULL); + } else { + manager->write_pointer(dg, _node_path.node()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int ParamNodePath:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = ParamValueBase::complete_pointers(p_list, manager); + _node_path = NodePath(DCAST(PandaNode, p_list[pi++])); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type ParamValue is encountered +// in the Bam file. It should create the ParamValue +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *ParamNodePath:: +make_from_bam(const FactoryParams ¶ms) { + ParamNodePath *param = new ParamNodePath; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + param->fillin(scan, manager); + + return param; +} + +//////////////////////////////////////////////////////////////////// +// Function: ParamNodePath::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new ParamValue. +//////////////////////////////////////////////////////////////////// +void ParamNodePath:: +fillin(DatagramIterator &scan, BamReader *manager) { + ParamValueBase::fillin(scan, manager); + manager->read_pointer(scan); +} diff --git a/panda/src/pgraph/paramNodePath.h b/panda/src/pgraph/paramNodePath.h new file mode 100644 index 0000000000..f1634c49ba --- /dev/null +++ b/panda/src/pgraph/paramNodePath.h @@ -0,0 +1,75 @@ +// Filename: paramNodePath.h +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PARAMNODEPATH_H +#define PARAMNODEPATH_H + +#include "pandabase.h" +#include "paramValue.h" +#include "nodePath.h" + +//////////////////////////////////////////////////////////////////// +// Class : ParamNodePath +// Description : A class object for storing a NodePath as a parameter. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_GOBJ ParamNodePath : public ParamValueBase { +protected: + INLINE ParamNodePath() {}; + +PUBLISHED: + INLINE ParamNodePath(const NodePath &node_path); + +#ifdef USE_MOVE_SEMANTICS + INLINE ParamNodePath(NodePath &&node_path) NOEXCEPT; +#endif + + INLINE virtual TypeHandle get_value_type() const; + INLINE const NodePath &get_value() const; + + virtual void output(ostream &out) const; + +private: + NodePath _node_path; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, + BamReader *manager); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +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() { + ParamValueBase::init_type(); + register_type(_type_handle, "ParamNodePath", + ParamValueBase::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "paramNodePath.I" + +#endif diff --git a/panda/src/pgraph/shaderInput.I b/panda/src/pgraph/shaderInput.I index b75724abea..c7aed1de80 100644 --- a/panda/src/pgraph/shaderInput.I +++ b/panda/src/pgraph/shaderInput.I @@ -119,23 +119,6 @@ ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority) : { } -//////////////////////////////////////////////////////////////////// -// Function: ShaderInput::Constructor -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE ShaderInput:: -ShaderInput(CPT_InternalName name, const NodePath &np, int priority) : - _name(MOVE(name)), - _type(M_nodepath), - _priority(priority), - _stored_nodepath(np), - _bind_layer(0), - _bind_level(0), - _access(A_read) -{ -} - //////////////////////////////////////////////////////////////////// // Function: ShaderInput::Constructor // Access: Published @@ -678,16 +661,6 @@ get_texture() const { return DCAST(Texture, _value); } -//////////////////////////////////////////////////////////////////// -// Function: ShaderInput::get_nodepath -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE const NodePath &ShaderInput:: -get_nodepath() const { - return _stored_nodepath; -} - //////////////////////////////////////////////////////////////////// // Function: ShaderInput::get_vector // Access: Published diff --git a/panda/src/pgraph/shaderInput.cxx b/panda/src/pgraph/shaderInput.cxx index a456d77900..8ab7ef3b1a 100644 --- a/panda/src/pgraph/shaderInput.cxx +++ b/panda/src/pgraph/shaderInput.cxx @@ -13,6 +13,7 @@ //////////////////////////////////////////////////////////////////// #include "shaderInput.h" +#include "paramNodePath.h" TypeHandle ShaderInput::_type_handle; @@ -32,13 +33,40 @@ get_blank() { return blank; } +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +ShaderInput:: +ShaderInput(CPT_InternalName name, const NodePath &np, int priority) : + _name(MOVE(name)), + _type(M_nodepath), + _priority(priority), + _value(new ParamNodePath(np)), + _bind_layer(0), + _bind_level(0), + _access(A_read) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::get_nodepath +// Access: Published +// Description: Warning: no error checking is done. This *will* +// crash if get_value_type() is not M_nodepath. +//////////////////////////////////////////////////////////////////// +const NodePath &ShaderInput:: +get_nodepath() const { + return DCAST(ParamNodePath, _value)->get_value(); +} + //////////////////////////////////////////////////////////////////// // Function: ShaderInput::register_with_read_factory // Access: Public, Static -// Description: +// Description: //////////////////////////////////////////////////////////////////// void ShaderInput:: register_with_read_factory() { // IMPLEMENT ME } - diff --git a/panda/src/pgraph/shaderInput.h b/panda/src/pgraph/shaderInput.h index fed3aebe5c..26c7e2e375 100644 --- a/panda/src/pgraph/shaderInput.h +++ b/panda/src/pgraph/shaderInput.h @@ -19,7 +19,6 @@ #include "pandabase.h" #include "typedWritableReferenceCount.h" #include "pointerTo.h" -#include "nodePath.h" #include "internalName.h" #include "paramValue.h" #include "pta_float.h" @@ -53,7 +52,6 @@ PUBLISHED: static const ShaderInput *get_blank(); INLINE ShaderInput(CPT_InternalName name, int priority=0); - INLINE ShaderInput(CPT_InternalName name, const NodePath &np, int priority=0); INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0); INLINE ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority=0); INLINE ShaderInput(CPT_InternalName name, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0); @@ -90,6 +88,8 @@ PUBLISHED: INLINE ShaderInput(CPT_InternalName name, const LVecBase3i &vec, int priority=0); INLINE ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority=0); + ShaderInput(CPT_InternalName name, const NodePath &np, int priority=0); + enum ShaderInputType { M_invalid = 0, M_texture, @@ -105,11 +105,12 @@ PUBLISHED: INLINE int get_value_type() const; INLINE int get_priority() const; INLINE Texture *get_texture() const; - INLINE const NodePath &get_nodepath() const; INLINE const LVecBase4 &get_vector() const; INLINE const Shader::ShaderPtrData &get_ptr() const; INLINE const SamplerState &get_sampler() const; + const NodePath &get_nodepath() const; + public: INLINE ParamValueBase *get_param() const; @@ -118,7 +119,6 @@ public: private: SamplerState _sampler; LVecBase4 _stored_vector; - NodePath _stored_nodepath; Shader::ShaderPtrData _stored_ptr; CPT_InternalName _name; PT(TypedWritableReferenceCount) _value; From 52fec094bcc2fa4a2b38b44e0d48d74673bafdf2 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 25 Feb 2015 16:24:56 +0100 Subject: [PATCH 17/20] Automatically coerce Python function to CallbackObject --- panda/src/putil/Sources.pp | 2 ++ panda/src/putil/callbackObject.h | 2 ++ panda/src/putil/callbackObject_ext.I | 32 +++++++++++++++++++ panda/src/putil/callbackObject_ext.h | 47 ++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 panda/src/putil/callbackObject_ext.I create mode 100644 panda/src/putil/callbackObject_ext.h diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index 7dc82eb5f4..8c72159364 100644 --- a/panda/src/putil/Sources.pp +++ b/panda/src/putil/Sources.pp @@ -27,6 +27,7 @@ cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \ callbackData.h callbackData.I \ callbackObject.h callbackObject.I \ + callbackObject_ext.h callbackObject_ext.I \ clockObject.h clockObject.I \ collideMask.h \ copyOnWriteObject.h copyOnWriteObject.I \ @@ -139,6 +140,7 @@ cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \ callbackData.h callbackData.I \ callbackObject.h callbackObject.I \ + callbackObject_ext.h callbackObject_ext.I \ clockObject.h clockObject.I \ collideMask.h \ copyOnWriteObject.h copyOnWriteObject.I \ diff --git a/panda/src/putil/callbackObject.h b/panda/src/putil/callbackObject.h index a8680e32fa..bb4f8f1223 100644 --- a/panda/src/putil/callbackObject.h +++ b/panda/src/putil/callbackObject.h @@ -38,6 +38,8 @@ public: PUBLISHED: virtual void output(ostream &out) const; + EXTENSION(static PT(CallbackObject) make(PyObject *function)); + public: virtual void do_callback(CallbackData *cbdata); diff --git a/panda/src/putil/callbackObject_ext.I b/panda/src/putil/callbackObject_ext.I new file mode 100644 index 0000000000..0bf73b2e01 --- /dev/null +++ b/panda/src/putil/callbackObject_ext.I @@ -0,0 +1,32 @@ +// Filename: callbackObject_ext.I +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: Extension::make +// Access: Published +// Description: This static constructor is merely provided so that +// interrogate can automatically coerce Python +// functions when passing them to a C++ function that +// accepts a CallbackObject. +//////////////////////////////////////////////////////////////////// +INLINE PT(CallbackObject) Extension:: +make(PyObject *function) { + if (function != Py_None && !PyCallable_Check(function)) { + PyErr_SetString(PyExc_TypeError, "expected callable or None"); + return NULL; + } else { + return new PythonCallbackObject(function); + } +} diff --git a/panda/src/putil/callbackObject_ext.h b/panda/src/putil/callbackObject_ext.h new file mode 100644 index 0000000000..1e0ceac72f --- /dev/null +++ b/panda/src/putil/callbackObject_ext.h @@ -0,0 +1,47 @@ +// Filename: callbackObject_ext.h +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 CALLBACKOBJECT_EXT_H +#define CALLBACKOBJECT_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "pythonCallbackObject.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// CallbackObject, which are called instead of +// any C++ methods with the same prototype. +// +// This just defines a static constructor, which makes +// it possible for Interrogate to automatically accept +// a Python function wherever a CallbackObject is +// accepted. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + INLINE static PT(CallbackObject) make(PyObject *function); +}; + +#include "callbackObject_ext.I" + +#endif // HAVE_PYTHON + +#endif // CALLBACKOBJECT_EXT_H From c3d1079b5aaf7abb397fee0543a499f27084bce8 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 23 Feb 2015 12:24:32 -0800 Subject: [PATCH 18/20] Fix missing dependency making parallel builds unreliable. --- makepanda/makepanda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index e61b24f756..72d30a5dab 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -4609,7 +4609,7 @@ if (PkgSkip("DIRECT")==0): OPTS=['DIR:direct/src/dcparser', 'WITHINPANDA', 'BUILDING:DIRECT', 'BISONPREFIX_dcyy'] CreateFile(GetOutputDir()+"/include/dcParser.h") TargetAdd('p3dcparser_dcParser.obj', opts=OPTS, input='dcParser.yxx') - TargetAdd('dcParser.h', input='p3egg_parser.obj', opts=['DEPENDENCYONLY']) + TargetAdd('dcParser.h', input='p3dcparser_dcParser.obj', opts=['DEPENDENCYONLY']) TargetAdd('p3dcparser_dcLexer.obj', opts=OPTS, input='dcLexer.lxx') TargetAdd('p3dcparser_composite1.obj', opts=OPTS, input='p3dcparser_composite1.cxx') TargetAdd('p3dcparser_composite2.obj', opts=OPTS, input='p3dcparser_composite2.cxx') From 72e1df987fcbf26d67049a1421b77eca6fe56f2b Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 25 Feb 2015 17:46:22 +0100 Subject: [PATCH 19/20] Fix pview issues with 1-frame animations and cycling between animations --- panda/src/framework/windowFramework.cxx | 44 ++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index 57505bb0d3..becd06ee18 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -798,15 +798,28 @@ next_anim_control() { if (_anim_controls_enabled) { destroy_anim_controls(); + if (_anim_controls.get_num_anims() == 0) { + set_anim_controls(false); + return; + } + + // Stop the active animation. + pause_button(); ++_anim_index; + if (_anim_index >= _anim_controls.get_num_anims()) { set_anim_controls(false); + _anim_controls.loop_all(true); } else { create_anim_controls(); + play_button(); } } else { _anim_index = 0; set_anim_controls(true); + if (_anim_controls.get_num_anims() > 0) { + play_button(); + } } } @@ -1451,6 +1464,23 @@ create_anim_controls() { AnimControl *control = _anim_controls.get_anim(_anim_index); nassertv(control != (AnimControl *)NULL); + if (control->get_num_frames() <= 1) { + // Don't show the controls when the animation has only 0 or 1 frames. + ostringstream text; + text << _anim_controls.get_anim_name(_anim_index); + text << " (" << control->get_num_frames() << " frame" + << ((control->get_num_frames() == 1) ? "" : "s") << ")"; + + PT(TextNode) label = new TextNode("label"); + label->set_align(TextNode::A_center); + label->set_text(text.str()); + NodePath tnp = _anim_controls_group.attach_new_node(label); + tnp.set_pos(0.0f, 0.0f, 0.07f); + tnp.set_scale(0.1f); + + return; + } + PT(TextNode) label = new TextNode("anim_name"); label->set_align(TextNode::A_left); label->set_text(_anim_controls.get_anim_name(_anim_index)); @@ -1525,13 +1555,17 @@ update_anim_controls() { AnimControl *control = _anim_controls.get_anim(_anim_index); nassertv(control != (AnimControl *)NULL); - if (_anim_slider->is_button_down()) { - control->pose((int)(_anim_slider->get_value() + 0.5)); - } else { - _anim_slider->set_value((PN_stdfloat)control->get_frame()); + if (_anim_slider != NULL) { + if (_anim_slider->is_button_down()) { + control->pose((int)(_anim_slider->get_value() + 0.5)); + } else { + _anim_slider->set_value((PN_stdfloat)control->get_frame()); + } } - _frame_number->set_text(format_string(control->get_frame())); + if (_frame_number != NULL) { + _frame_number->set_text(format_string(control->get_frame())); + } control->set_play_rate(_play_rate_slider->get_value()); } From db87bc791451a1eaf1bbbcdf6471ce387707f6f5 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 27 Feb 2015 12:45:11 +0100 Subject: [PATCH 20/20] PointerToArray fixes, Windows build fixes, more move constructors --- dtool/src/dtoolutil/filename.I | 69 ++++++++++++++++++++ dtool/src/dtoolutil/filename.h | 12 +++- makepanda/makepandacore.py | 6 +- panda/src/express/datagram.I | 27 ++++++++ panda/src/express/datagram.h | 5 ++ panda/src/express/pointerToArray.I | 90 ++++++++++++++++++++++++++ panda/src/express/pointerToArray.h | 23 +++++++ panda/src/express/pointerToArrayBase.I | 36 +++++++---- panda/src/express/pointerToArrayBase.h | 4 ++ panda/src/express/pointerToArray_ext.I | 64 +++++++++++------- panda/src/express/pointerToArray_ext.h | 20 ++++++ panda/src/mathutil/pta_LMatrix3_ext.h | 28 ++++++++ panda/src/mathutil/pta_LMatrix4_ext.h | 28 ++++++++ panda/src/mathutil/pta_LVecBase2_ext.h | 30 +++++++++ panda/src/mathutil/pta_LVecBase3_ext.h | 30 +++++++++ panda/src/mathutil/pta_LVecBase4_ext.h | 30 +++++++++ panda/src/pgraph/nodePath.h | 2 + 17 files changed, 468 insertions(+), 36 deletions(-) create mode 100755 panda/src/mathutil/pta_LMatrix3_ext.h create mode 100755 panda/src/mathutil/pta_LMatrix4_ext.h create mode 100755 panda/src/mathutil/pta_LVecBase2_ext.h create mode 100755 panda/src/mathutil/pta_LVecBase3_ext.h create mode 100755 panda/src/mathutil/pta_LVecBase4_ext.h diff --git a/dtool/src/dtoolutil/filename.I b/dtool/src/dtoolutil/filename.I index 675eb5afc6..22c49f39bf 100644 --- a/dtool/src/dtoolutil/filename.I +++ b/dtool/src/dtoolutil/filename.I @@ -64,6 +64,39 @@ Filename(const Filename ©) : { } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Filename::Move Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Filename:: +Filename(string &&filename) NOEXCEPT { + _flags = 0; + (*this) = move(filename); +} +#endif // USE_MOVE_SEMANTICS + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Filename::Move Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Filename:: +Filename(Filename &&from) NOEXCEPT : + _filename(move(from._filename)), + _dirname_end(from._dirname_end), + _basename_start(from._basename_start), + _basename_end(from._basename_end), + _extension_start(from._extension_start), + _hash_start(from._hash_start), + _hash_end(from._hash_end), + _flags(from._flags) +{ +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: Filename::text_filename named constructor // Access: Published @@ -216,6 +249,42 @@ operator = (const Filename ©) { return *this; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Filename::Move assignment operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Filename &Filename:: +operator = (string &&filename) NOEXCEPT { + _filename = move(filename); + + locate_basename(); + locate_extension(); + locate_hash(); + return *this; +} +#endif // USE_MOVE_SEMANTICS + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Filename::Move assignment operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Filename &Filename:: +operator = (Filename &&from) NOEXCEPT { + _filename = MOVE(from._filename); + _dirname_end = from._dirname_end; + _basename_start = from._basename_start; + _basename_end = from._basename_end; + _extension_start = from._extension_start; + _hash_start = from._hash_start; + _hash_end = from._hash_end; + _flags = from._flags; + return *this; +} +#endif // USE_MOVE_SEMANTICS //////////////////////////////////////////////////////////////////// // Function: Filename::string typecast operator diff --git a/dtool/src/dtoolutil/filename.h b/dtool/src/dtoolutil/filename.h index 493b912f69..45d975eac6 100644 --- a/dtool/src/dtoolutil/filename.h +++ b/dtool/src/dtoolutil/filename.h @@ -68,6 +68,11 @@ PUBLISHED: Filename(const Filename &dirname, const Filename &basename); INLINE ~Filename(); +#ifdef USE_MOVE_SEMANTICS + INLINE Filename(string &&filename) NOEXCEPT; + INLINE Filename(Filename &&from) NOEXCEPT; +#endif + #ifdef HAVE_PYTHON PyObject *__reduce__(PyObject *self) const; #endif @@ -88,7 +93,7 @@ PUBLISHED: Type type = T_general); static Filename from_os_specific_w(const wstring &os_specific, Type type = T_general); - static Filename expand_from(const string &user_string, + static Filename expand_from(const string &user_string, Type type = T_general); static Filename temporary(const string &dirname, const string &prefix, const string &suffix = string(), @@ -105,6 +110,11 @@ PUBLISHED: INLINE Filename &operator = (const char *filename); INLINE Filename &operator = (const Filename ©); +#ifdef USE_MOVE_SEMANTICS + INLINE Filename &operator = (string &&filename) NOEXCEPT; + INLINE Filename &operator = (Filename &&from) NOEXCEPT; +#endif + // And retrieval is by any of the classic string operations. INLINE operator const string & () const; INLINE const char *c_str() const; diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 138c372af3..9097948e98 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -210,6 +210,8 @@ def PrettyTime(t): return "%d sec" % (seconds) def ProgressOutput(progress, msg, target = None): + sys.stdout.flush() + sys.stderr.flush() prefix = "" thisthread = threading.currentThread() if thisthread is MAINTHREAD: @@ -235,6 +237,8 @@ def ProgressOutput(progress, msg, target = None): suffix = GetColor() print(''.join((prefix, msg, suffix))) + sys.stdout.flush() + sys.stderr.flush() def exit(msg = ""): sys.stdout.flush() @@ -498,7 +502,7 @@ def oscmd(cmd, ignoreError = False): print(GetColor("blue") + cmd.split(" ", 1)[0] + " " + GetColor("magenta") + cmd.split(" ", 1)[1] + GetColor()) sys.stdout.flush() - if sys.platform == "win32": + if sys.platform in ("win32", "cygwin"): exe = cmd.split()[0] exe_path = LocateBinary(exe) if exe_path is None: diff --git a/panda/src/express/datagram.I b/panda/src/express/datagram.I index 28c633a5c8..123d428b1b 100644 --- a/panda/src/express/datagram.I +++ b/panda/src/express/datagram.I @@ -82,6 +82,33 @@ operator = (const Datagram ©) { _stdfloat_double = copy._stdfloat_double; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Datagram::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Datagram:: +Datagram(Datagram &&from) NOEXCEPT : + _data(move(from._data)), + _stdfloat_double(from._stdfloat_double) +{ +} +#endif // USE_MOVE_SEMANTICS + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Datagram::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void Datagram:: +operator = (Datagram &&from) NOEXCEPT { + _data = move(from._data); + _stdfloat_double = from._stdfloat_double; +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: Datagram::add_bool // Access: Public diff --git a/panda/src/express/datagram.h b/panda/src/express/datagram.h index 71d44a018b..5de3ce6467 100644 --- a/panda/src/express/datagram.h +++ b/panda/src/express/datagram.h @@ -48,6 +48,11 @@ PUBLISHED: INLINE Datagram(const Datagram ©); INLINE void operator = (const Datagram ©); +#ifdef USE_MOVE_SEMANTICS + INLINE Datagram(Datagram &&from) NOEXCEPT; + INLINE void operator = (Datagram &&from) NOEXCEPT; +#endif + virtual ~Datagram(); virtual void clear(); diff --git a/panda/src/express/pointerToArray.I b/panda/src/express/pointerToArray.I index c833954570..dbb5f9a0bf 100644 --- a/panda/src/express/pointerToArray.I +++ b/panda/src/express/pointerToArray.I @@ -77,6 +77,21 @@ PointerToArray(const PointerToArray ©) : { } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PointerToArray::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PointerToArray:: +PointerToArray(PointerToArray &&from) NOEXCEPT : + PointerToArrayBase(move(from)), + _type_handle(from._type_handle) +{ +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: PointerToArray::begin // Access: Public @@ -682,6 +697,21 @@ operator = (const PointerToArray ©) { return *this; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PointerToArray::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PointerToArray &PointerToArray:: +operator = (PointerToArray &&from) NOEXCEPT { + _type_handle = from._type_handle; + ((PointerToArray *)this)->reassign(move(from)); + return *this; +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: PointerToArray::clear // Access: Public @@ -736,6 +766,36 @@ ConstPointerToArray(const ConstPointerToArray ©) : { } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerToArray:: +ConstPointerToArray(PointerToArray &&from) NOEXCEPT : + PointerToArrayBase(move(from)), + _type_handle(from._type_handle) +{ +} +#endif // USE_MOVE_SEMANTICS + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerToArray:: +ConstPointerToArray(ConstPointerToArray &&from) NOEXCEPT : + PointerToArrayBase(move(from)), + _type_handle(from._type_handle) +{ +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: ConstPointerToArray::begin // Access: Public @@ -1141,6 +1201,36 @@ operator = (const ConstPointerToArray ©) { return *this; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerToArray &ConstPointerToArray:: +operator = (PointerToArray &&from) NOEXCEPT { + _type_handle = from._type_handle; + ((ConstPointerToArray *)this)->reassign(move(from)); + return *this; +} +#endif // USE_MOVE_SEMANTICS + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerToArray &ConstPointerToArray:: +operator = (ConstPointerToArray &&from) NOEXCEPT { + _type_handle = from._type_handle; + ((ConstPointerToArray *)this)->reassign(move(from)); + return *this; +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: ConstPointerToArray::clear // Access: Public diff --git a/panda/src/express/pointerToArray.h b/panda/src/express/pointerToArray.h index 78b504d202..0f1d4cd5c8 100644 --- a/panda/src/express/pointerToArray.h +++ b/panda/src/express/pointerToArray.h @@ -151,6 +151,10 @@ public: INLINE PointerToArray(size_type n, const Element &value, TypeHandle type_handle = get_type_handle(Element)); INLINE PointerToArray(const PointerToArray ©); +#ifdef USE_MOVE_SEMANTICS + INLINE PointerToArray(PointerToArray &&from) NOEXCEPT; +#endif + public: // Duplicating the interface of vector. The following member // functions are all const, because they do not reassign the @@ -231,6 +235,12 @@ public: operator = (ReferenceCountedVector *ptr); INLINE PointerToArray & operator = (const PointerToArray ©); + +#ifdef USE_MOVE_SEMANTICS + INLINE PointerToArray & + operator = (PointerToArray &&from) NOEXCEPT; +#endif + INLINE void clear(); private: @@ -305,6 +315,11 @@ PUBLISHED: INLINE ConstPointerToArray(const PointerToArray ©); INLINE ConstPointerToArray(const ConstPointerToArray ©); +#ifdef USE_MOVE_SEMANTICS + INLINE ConstPointerToArray(PointerToArray &&from) NOEXCEPT; + INLINE ConstPointerToArray(ConstPointerToArray &&from) NOEXCEPT; +#endif + // Duplicating the interface of vector. INLINE iterator begin() const; @@ -355,6 +370,14 @@ PUBLISHED: operator = (const PointerToArray ©); INLINE ConstPointerToArray & operator = (const ConstPointerToArray ©); + +#ifdef USE_MOVE_SEMANTICS + INLINE ConstPointerToArray & + operator = (PointerToArray &&from) NOEXCEPT; + INLINE ConstPointerToArray & + operator = (ConstPointerToArray &&from) NOEXCEPT; +#endif + INLINE void clear(); private: diff --git a/panda/src/express/pointerToArrayBase.I b/panda/src/express/pointerToArrayBase.I index f8f5e91769..343fb7374d 100644 --- a/panda/src/express/pointerToArrayBase.I +++ b/panda/src/express/pointerToArrayBase.I @@ -57,11 +57,11 @@ template INLINE ReferenceCountedVector:: ~ReferenceCountedVector() { } - + //////////////////////////////////////////////////////////////////// // Function: ReferenceCountedVector::size // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE TYPENAME ReferenceCountedVector::size_type ReferenceCountedVector:: @@ -72,7 +72,7 @@ size() const { //////////////////////////////////////////////////////////////////// // Function: ReferenceCountedVector::insert // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE TYPENAME ReferenceCountedVector::iterator ReferenceCountedVector:: @@ -83,7 +83,7 @@ insert(iterator position, const Element &x) { //////////////////////////////////////////////////////////////////// // Function: ReferenceCountedVector::insert // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE void ReferenceCountedVector:: @@ -94,7 +94,7 @@ insert(iterator position, size_type n, const Element &x) { //////////////////////////////////////////////////////////////////// // Function: ReferenceCountedVector::erase // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE void ReferenceCountedVector:: @@ -105,7 +105,7 @@ erase(iterator position) { //////////////////////////////////////////////////////////////////// // Function: ReferenceCountedVector::erase // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE void ReferenceCountedVector:: @@ -116,7 +116,7 @@ erase(iterator first, iterator last) { //////////////////////////////////////////////////////////////////// // Function: ReferenceCountedVector::pop_back // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE void ReferenceCountedVector:: @@ -127,7 +127,7 @@ pop_back() { //////////////////////////////////////////////////////////////////// // Function: ReferenceCountedVector::clear // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE void ReferenceCountedVector:: @@ -138,7 +138,7 @@ clear() { //////////////////////////////////////////////////////////////////// // Function: PointerToArrayBase::Constructor // Access: Protected -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE PointerToArrayBase:: @@ -150,7 +150,7 @@ PointerToArrayBase(ReferenceCountedVector *ptr) : //////////////////////////////////////////////////////////////////// // Function: PointerToArrayBase::Copy Constructor // Access: Protected -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE PointerToArrayBase:: @@ -159,10 +159,24 @@ PointerToArrayBase(const PointerToArrayBase ©) : { } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PointerToArrayBase::Move Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PointerToArrayBase:: +PointerToArrayBase(PointerToArrayBase &&from) NOEXCEPT : + PointerToBase >(move(from)) +{ +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: PointerToArrayBase::Destructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE PointerToArrayBase:: diff --git a/panda/src/express/pointerToArrayBase.h b/panda/src/express/pointerToArrayBase.h index c660a3b0f2..fe481842be 100644 --- a/panda/src/express/pointerToArrayBase.h +++ b/panda/src/express/pointerToArrayBase.h @@ -82,6 +82,10 @@ protected: INLINE PointerToArrayBase(ReferenceCountedVector *ptr); INLINE PointerToArrayBase(const PointerToArrayBase ©); +#ifdef USE_MOVE_SEMANTICS + INLINE PointerToArrayBase(PointerToArrayBase &&from) NOEXCEPT; +#endif + PUBLISHED: INLINE ~PointerToArrayBase(); }; diff --git a/panda/src/express/pointerToArray_ext.I b/panda/src/express/pointerToArray_ext.I index c53b0c3ee0..f8a1ffc600 100644 --- a/panda/src/express/pointerToArray_ext.I +++ b/panda/src/express/pointerToArray_ext.I @@ -22,26 +22,33 @@ // Python buffer protocol. //////////////////////////////////////////////////////////////////// template -void Extension >:: +INLINE void Extension >:: __init__(PyObject *self, PyObject *source) { #if PY_VERSION_HEX >= 0x02060000 if (PyObject_CheckBuffer(source)) { // User passed a buffer object. Py_buffer view; if (PyObject_GetBuffer(source, &view, PyBUF_CONTIG_RO) == -1) { - PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a contiguous buffer"); + PyErr_SetString(PyExc_TypeError, + "PointerToArray constructor requires a contiguous buffer"); return; } if (view.itemsize != 1 && view.itemsize != sizeof(Element)) { - PyErr_SetString(PyExc_TypeError, "buffer.itemsize does not match PointerToArray element size"); + PyErr_SetString(PyExc_TypeError, + "buffer.itemsize does not match PointerToArray element size"); return; } - int num_elements = view.len / sizeof(Element); - this->_this->insert(this->_this->begin(), num_elements, Element()); + if (view.len % sizeof(Element) != 0) { + PyErr_Format(PyExc_ValueError, + "byte buffer is not a multiple of %zu bytes", + sizeof(Element)); + return; + } if (view.len > 0) { + this->_this->resize(view.len / sizeof(Element)); memcpy(this->_this->p(), view.buf, view.len); } @@ -52,21 +59,22 @@ __init__(PyObject *self, PyObject *source) { if (!PySequence_Check(source)) { // If passed with a non-sequence, this isn't the right constructor. - PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a sequence or buffer object"); + PyErr_SetString(PyExc_TypeError, + "PointerToArray constructor requires a sequence or buffer object"); return; } // If we were passed a Python string, then instead of storing it // character-at-a-time, just load the whole string as a data - // buffer. + // buffer. Not sure if this case is still necessary - don't Python + // str/bytes objects export the buffer protocol, as above? #if PY_MAJOR_VERSION >= 3 if (PyBytes_Check(source)) { int size = PyBytes_Size(source); if (size % sizeof(Element) != 0) { - ostringstream stream; - stream << "Buffer not a multiple of " << sizeof(Element) << " bytes"; - string str = stream.str(); - PyErr_SetString(PyExc_ValueError, str.c_str()); + PyErr_Format(PyExc_ValueError, + "bytes object is not a multiple of %zu bytes", + sizeof(Element)); return; } @@ -85,10 +93,9 @@ __init__(PyObject *self, PyObject *source) { if (PyString_CheckExact(source)) { int size = PyString_Size(source); if (size % sizeof(Element) != 0) { - ostringstream stream; - stream << "Buffer not a multiple of " << sizeof(Element) << " bytes"; - string str = stream.str(); - PyErr_SetString(PyExc_ValueError, str.c_str()); + PyErr_Format(PyExc_ValueError, + "str object is not a multiple of %zu bytes", + sizeof(Element)); return; } @@ -107,20 +114,29 @@ __init__(PyObject *self, PyObject *source) { // Now construct the internal list by copying the elements // one-at-a-time from Python. + PyObject *push_back = PyObject_GetAttrString(self, "push_back"); + if (push_back == NULL) { + PyErr_BadArgument(); + return; + } + + // We need to initialize the this pointer before we can call push_back. + ((Dtool_PyInstDef *)self)->_ptr_to_object = (void *)this->_this; + int size = PySequence_Size(source); for (int i = 0; i < size; ++i) { PyObject *item = PySequence_GetItem(source, i); if (item == NULL) { return; } - PyObject *result = PyObject_CallMethod(self, (char *)"push_back", (char *)"O", item); + PyObject *result = PyObject_CallFunctionObjArgs(push_back, item, NULL); Py_DECREF(item); if (result == NULL) { // Unable to add item--probably it wasn't of the appropriate type. - ostringstream stream; - stream << "Element " << i << " in sequence passed to PointerToArray constructor could not be added"; - string str = stream.str(); - PyErr_SetString(PyExc_TypeError, str.c_str()); + PyErr_Print(); + PyErr_Format(PyExc_TypeError, + "Element %d in sequence passed to PointerToArray " + "constructor could not be added", i); return; } Py_DECREF(result); @@ -161,7 +177,9 @@ __setitem__(size_t n, const Element &value) { template INLINE void Extension >:: __init__(PyObject *self, PyObject *source) { - new (this->_this) ConstPointerToArray(get_type_handle(Element)); + PointerToArray array; + invoke_extension(&array).__init__(self, source); + *(this->_this) = MOVE(array); } //////////////////////////////////////////////////////////////////// @@ -240,7 +258,7 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const { if (view->internal != NULL) { // Oh, right, let's not forget to unref this. - ((const PointerToArray *) view->internal)->unref(); + unref_delete((const PointerToArray *)view->internal); view->internal = NULL; } } @@ -314,7 +332,7 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const { if (view->internal != NULL) { // Oh, right, let's not forget to unref this. - ((const PointerToArray *) view->internal)->unref(); + unref_delete((const PointerToArray *)view->internal); view->internal = NULL; } } diff --git a/panda/src/express/pointerToArray_ext.h b/panda/src/express/pointerToArray_ext.h index b403ed4dc6..c4f7afdfec 100644 --- a/panda/src/express/pointerToArray_ext.h +++ b/panda/src/express/pointerToArray_ext.h @@ -66,6 +66,26 @@ public: #endif }; +#ifdef _MSC_VER +// Ugh... MSVC needs this because they still don't have a decent linker. +#include "PTA_uchar.h" +#include "PTA_ushort.h" +#include "PTA_float.h" +#include "PTA_double.h" +#include "PTA_int.h" + +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +#endif + // This macro is used to map a data type to a format code // as used in the Python 'struct' and 'array' modules. #define get_format_code(type) _get_format_code((const type *)0) diff --git a/panda/src/mathutil/pta_LMatrix3_ext.h b/panda/src/mathutil/pta_LMatrix3_ext.h new file mode 100755 index 0000000000..4cda107aef --- /dev/null +++ b/panda/src/mathutil/pta_LMatrix3_ext.h @@ -0,0 +1,28 @@ +// Filename: pta_LMatrix3_ext.h +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PTA_LMATRIX3_EXT_H +#define PTA_LMATRIX3_EXT_H + +#include "pointerToArray_ext.h" +#include "pta_LMatrix3.h" + +#if defined(_MSC_VER) && !defined(CPPPARSER) +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +#endif + +#endif diff --git a/panda/src/mathutil/pta_LMatrix4_ext.h b/panda/src/mathutil/pta_LMatrix4_ext.h new file mode 100755 index 0000000000..02a1e86dd8 --- /dev/null +++ b/panda/src/mathutil/pta_LMatrix4_ext.h @@ -0,0 +1,28 @@ +// Filename: pta_LMatrix4_ext.h +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PTA_LMATRIX4_EXT_H +#define PTA_LMATRIX4_EXT_H + +#include "pointerToArray_ext.h" +#include "pta_LMatrix4.h" + +#if defined(_MSC_VER) && !defined(CPPPARSER) +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +#endif + +#endif diff --git a/panda/src/mathutil/pta_LVecBase2_ext.h b/panda/src/mathutil/pta_LVecBase2_ext.h new file mode 100755 index 0000000000..4624ec604f --- /dev/null +++ b/panda/src/mathutil/pta_LVecBase2_ext.h @@ -0,0 +1,30 @@ +// Filename: pta_LVecBase2_ext.h +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PTA_LVECBASE2_EXT_H +#define PTA_LVECBASE2_EXT_H + +#include "pointerToArray_ext.h" +#include "pta_LVecBase2.h" + +#if defined(_MSC_VER) && !defined(CPPPARSER) +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +#endif + +#endif diff --git a/panda/src/mathutil/pta_LVecBase3_ext.h b/panda/src/mathutil/pta_LVecBase3_ext.h new file mode 100755 index 0000000000..2ae87f518f --- /dev/null +++ b/panda/src/mathutil/pta_LVecBase3_ext.h @@ -0,0 +1,30 @@ +// Filename: pta_LVecBase3_ext.h +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PTA_LVECBASE3_EXT_H +#define PTA_LVECBASE3_EXT_H + +#include "pointerToArray_ext.h" +#include "pta_LVecBase3.h" + +#if defined(_MSC_VER) && !defined(CPPPARSER) +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +#endif + +#endif diff --git a/panda/src/mathutil/pta_LVecBase4_ext.h b/panda/src/mathutil/pta_LVecBase4_ext.h new file mode 100755 index 0000000000..29eee6530a --- /dev/null +++ b/panda/src/mathutil/pta_LVecBase4_ext.h @@ -0,0 +1,30 @@ +// Filename: pta_LVecBase4_ext.h +// Created by: rdb (25Feb15) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PTA_LVECBASE4_EXT_H +#define PTA_LVECBASE4_EXT_H + +#include "pointerToArray_ext.h" +#include "pta_LVecBase4.h" + +#if defined(_MSC_VER) && !defined(CPPPARSER) +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +template class EXPORT_THIS Extension; +#endif + +#endif diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index d84519547d..8163e78767 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -39,6 +39,8 @@ #include "pta_LVecBase2.h" #include "stl_compares.h" #include "shaderInput.h" +#include "textureCollection.h" +#include "textureStageCollection.h" class NodePathCollection; class FindApproxPath;