Merge branch 'master' into interrogate-overhaul

This commit is contained in:
rdb 2015-02-27 12:48:33 +01:00
commit 238cbad2a1
62 changed files with 1828 additions and 467 deletions

View File

@ -60,7 +60,7 @@ extern char **environ;
#include <sys/sysctl.h>
#endif
#if defined(IS_LINUX) || defined(IS_OSX)
#if defined(IS_LINUX) || defined(IS_OSX) || defined(IS_FREEBSD)
// For link_map and dlinfo.
#include <link.h>
#include <dlfcn.h>

View File

@ -64,6 +64,39 @@ Filename(const Filename &copy) :
{
}
#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 &copy) {
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

View File

@ -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
EXTENSION(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 &copy);
#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;

View File

@ -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')

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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();

View File

@ -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())) {

View File

@ -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__
}

View File

@ -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 &center, 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<LPoint3d> vpos;
vpos.reserve(num_vertices);
@ -3178,7 +3179,7 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
pset<EggVertex *>::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<LVertex> 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

View File

@ -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"
@ -347,7 +348,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);
@ -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

View File

@ -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"

View File

@ -82,6 +82,33 @@ operator = (const Datagram &copy) {
_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

View File

@ -48,6 +48,11 @@ PUBLISHED:
INLINE Datagram(const Datagram &copy);
INLINE void operator = (const Datagram &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE Datagram(Datagram &&from) NOEXCEPT;
INLINE void operator = (Datagram &&from) NOEXCEPT;
#endif
virtual ~Datagram();
virtual void clear();

View File

@ -77,6 +77,21 @@ PointerToArray(const PointerToArray<Element> &copy) :
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::Move Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArray<Element>::
PointerToArray(PointerToArray<Element> &&from) NOEXCEPT :
PointerToArrayBase<Element>(move(from)),
_type_handle(from._type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::begin
// Access: Public
@ -682,6 +697,21 @@ operator = (const PointerToArray<Element> &copy) {
return *this;
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::Assignment operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArray<Element> &PointerToArray<Element>::
operator = (PointerToArray<Element> &&from) NOEXCEPT {
_type_handle = from._type_handle;
((PointerToArray<Element> *)this)->reassign(move(from));
return *this;
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::clear
// Access: Public
@ -736,6 +766,36 @@ ConstPointerToArray(const ConstPointerToArray<Element> &copy) :
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Move Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element>::
ConstPointerToArray(PointerToArray<Element> &&from) NOEXCEPT :
PointerToArrayBase<Element>(move(from)),
_type_handle(from._type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Move Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element>::
ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT :
PointerToArrayBase<Element>(move(from)),
_type_handle(from._type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::begin
// Access: Public
@ -1141,6 +1201,36 @@ operator = (const ConstPointerToArray<Element> &copy) {
return *this;
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Assignment operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
operator = (PointerToArray<Element> &&from) NOEXCEPT {
_type_handle = from._type_handle;
((ConstPointerToArray<Element> *)this)->reassign(move(from));
return *this;
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Assignment operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
operator = (ConstPointerToArray<Element> &&from) NOEXCEPT {
_type_handle = from._type_handle;
((ConstPointerToArray<Element> *)this)->reassign(move(from));
return *this;
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::clear
// Access: Public

View File

@ -151,6 +151,10 @@ public:
INLINE PointerToArray(size_type n, const Element &value, TypeHandle type_handle = get_type_handle(Element));
INLINE PointerToArray(const PointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE PointerToArray(PointerToArray<Element> &&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<Element> *ptr);
INLINE PointerToArray<Element> &
operator = (const PointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE PointerToArray<Element> &
operator = (PointerToArray<Element> &&from) NOEXCEPT;
#endif
INLINE void clear();
private:
@ -305,6 +315,11 @@ PUBLISHED:
INLINE ConstPointerToArray(const PointerToArray<Element> &copy);
INLINE ConstPointerToArray(const ConstPointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE ConstPointerToArray(PointerToArray<Element> &&from) NOEXCEPT;
INLINE ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT;
#endif
// Duplicating the interface of vector.
INLINE iterator begin() const;
@ -355,6 +370,14 @@ PUBLISHED:
operator = (const PointerToArray<Element> &copy);
INLINE ConstPointerToArray<Element> &
operator = (const ConstPointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE ConstPointerToArray<Element> &
operator = (PointerToArray<Element> &&from) NOEXCEPT;
INLINE ConstPointerToArray<Element> &
operator = (ConstPointerToArray<Element> &&from) NOEXCEPT;
#endif
INLINE void clear();
private:

View File

@ -57,11 +57,11 @@ template<class Element>
INLINE ReferenceCountedVector<Element>::
~ReferenceCountedVector() {
}
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::size
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE TYPENAME ReferenceCountedVector<Element>::size_type ReferenceCountedVector<Element>::
@ -72,7 +72,7 @@ size() const {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::insert
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE TYPENAME ReferenceCountedVector<Element>::iterator ReferenceCountedVector<Element>::
@ -83,7 +83,7 @@ insert(iterator position, const Element &x) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::insert
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -94,7 +94,7 @@ insert(iterator position, size_type n, const Element &x) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::erase
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -105,7 +105,7 @@ erase(iterator position) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::erase
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -116,7 +116,7 @@ erase(iterator first, iterator last) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::pop_back
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -127,7 +127,7 @@ pop_back() {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::clear
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -138,7 +138,7 @@ clear() {
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Constructor
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::
@ -150,7 +150,7 @@ PointerToArrayBase(ReferenceCountedVector<Element> *ptr) :
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Copy Constructor
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::
@ -159,10 +159,24 @@ PointerToArrayBase(const PointerToArrayBase<Element> &copy) :
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Move Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::
PointerToArrayBase(PointerToArrayBase<Element> &&from) NOEXCEPT :
PointerToBase<ReferenceCountedVector<Element> >(move(from))
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Destructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::

View File

@ -82,6 +82,10 @@ protected:
INLINE PointerToArrayBase(ReferenceCountedVector<Element> *ptr);
INLINE PointerToArrayBase(const PointerToArrayBase<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE PointerToArrayBase(PointerToArrayBase<Element> &&from) NOEXCEPT;
#endif
PUBLISHED:
INLINE ~PointerToArrayBase();
};

View File

@ -22,26 +22,33 @@
// Python buffer protocol.
////////////////////////////////////////////////////////////////////
template<class Element>
void Extension<PointerToArray<Element> >::
INLINE void Extension<PointerToArray<Element> >::
__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<class Element>
INLINE void Extension<ConstPointerToArray<Element> >::
__init__(PyObject *self, PyObject *source) {
new (this->_this) ConstPointerToArray<Element>(get_type_handle(Element));
PointerToArray<Element> 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<Element> *) view->internal)->unref();
unref_delete((const PointerToArray<Element> *)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<Element> *) view->internal)->unref();
unref_delete((const PointerToArray<Element> *)view->internal);
view->internal = NULL;
}
}

View File

@ -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<PTA_uchar>;
template class EXPORT_THIS Extension<PTA_ushort>;
template class EXPORT_THIS Extension<PTA_float>;
template class EXPORT_THIS Extension<PTA_double>;
template class EXPORT_THIS Extension<PTA_int>;
template class EXPORT_THIS Extension<CPTA_uchar>;
template class EXPORT_THIS Extension<CPTA_ushort>;
template class EXPORT_THIS Extension<CPTA_float>;
template class EXPORT_THIS Extension<CPTA_double>;
template class EXPORT_THIS Extension<CPTA_int>;
#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)

View File

@ -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);
@ -313,8 +319,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

View File

@ -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();

View File

@ -794,15 +794,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();
}
}
}
@ -1447,6 +1460,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));
@ -1521,13 +1551,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());
}

View File

@ -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;

View File

@ -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;

View File

@ -18,6 +18,7 @@
#include "pandabase.h"
#include "adaptiveLru.h"
#include "simpleLru.h"
#include "samplerState.h"
#include "savedContext.h"

View File

@ -21,6 +21,7 @@
#include "namable.h"
#include "luse.h"
#include "numeric_types.h"
#include "bamReader.h"
#include "config_gobj.h"
class FactoryParams;

View File

@ -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) &&

View File

@ -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) &&

View File

@ -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<PTA_LMatrix3f>;
template class EXPORT_THIS Extension<PTA_LMatrix3d>;
template class EXPORT_THIS Extension<CPTA_LMatrix3f>;
template class EXPORT_THIS Extension<CPTA_LMatrix3d>;
#endif
#endif

View File

@ -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<PTA_LMatrix4f>;
template class EXPORT_THIS Extension<PTA_LMatrix4d>;
template class EXPORT_THIS Extension<CPTA_LMatrix4f>;
template class EXPORT_THIS Extension<CPTA_LMatrix4d>;
#endif
#endif

View File

@ -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<PTA_LVecBase2f>;
template class EXPORT_THIS Extension<PTA_LVecBase2d>;
template class EXPORT_THIS Extension<PTA_LVecBase2i>;
template class EXPORT_THIS Extension<CPTA_LVecBase2f>;
template class EXPORT_THIS Extension<CPTA_LVecBase2d>;
template class EXPORT_THIS Extension<CPTA_LVecBase2i>;
#endif
#endif

View File

@ -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<PTA_LVecBase3f>;
template class EXPORT_THIS Extension<PTA_LVecBase3d>;
template class EXPORT_THIS Extension<PTA_LVecBase3i>;
template class EXPORT_THIS Extension<CPTA_LVecBase3f>;
template class EXPORT_THIS Extension<CPTA_LVecBase3d>;
template class EXPORT_THIS Extension<CPTA_LVecBase3i>;
#endif
#endif

View File

@ -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<PTA_LVecBase4f>;
template class EXPORT_THIS Extension<PTA_LVecBase4d>;
template class EXPORT_THIS Extension<PTA_LVecBase4i>;
template class EXPORT_THIS Extension<CPTA_LVecBase4f>;
template class EXPORT_THIS Extension<CPTA_LVecBase4d>;
template class EXPORT_THIS Extension<CPTA_LVecBase4i>;
#endif
#endif

View File

@ -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 \

View File

@ -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();

View File

@ -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"

View File

@ -38,6 +38,9 @@
#include "pta_LVecBase3.h"
#include "pta_LVecBase2.h"
#include "stl_compares.h"
#include "shaderInput.h"
#include "textureCollection.h"
#include "textureStageCollection.h"
class NodePathCollection;
class FindApproxPath;
@ -1009,9 +1012,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

View File

@ -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"

View File

@ -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;
}

View File

@ -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 &params) {
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);
}

View File

@ -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 &params);
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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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
}

View File

@ -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;

View File

@ -18,6 +18,7 @@
#include "virtualFileSystem.h"
#include "loader.h"
#include "shader.h"
#include "string_utils.h"
ShaderPool *ShaderPool::_global_ptr = (ShaderPool *)NULL;

View File

@ -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 \
@ -138,6 +139,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 \

View File

@ -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);

View File

@ -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<CallbackObject>::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<CallbackObject>::
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);
}
}

View File

@ -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<CallbackObject>
// 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<CallbackObject> : public ExtensionBase<CallbackObject> {
public:
INLINE static PT(CallbackObject) make(PyObject *function);
};
#include "callbackObject_ext.I"
#endif // HAVE_PYTHON
#endif // CALLBACKOBJECT_EXT_H

View File

@ -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 <Bundle> 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>");
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<float> &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<float> &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<float> &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<float>::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);
//}
}
}

View File

@ -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<Joint> Joints;
typedef pmap<string, Joint> 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<float> &keys);
void r_collect_keys(FCDSceneNode *node, pset<float> &keys);
void build_table(EggTable *parent, FCDSceneNode* node, const pset<float> &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<string, FCDSkinControllerJoint*> _controller_joints;
const FCDSkinController *_skin_controller;
Joints _joints;
JointMap _bound_joints;
public:
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -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 <double_sided> tag to be either 1 or 0, found '" << enode->GetContent() << "' instead" << endl;
daeegg_cat.warning() << "Expected <double_sided> 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;

View File

@ -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 <extra> tag
const FCDExtra* extra = visual_scene->GetExtra();
//FIXME: eek this looks horrid
if (extra != NULL) {
const FCDEType* etype = extra->GetDefaultType();
if (etype != NULL) {
const FCDENode* enode = (const FCDENode*) etype->FindTechnique("MAX3D");
if (enode != NULL) {
enode = enode->FindChildNode("frame_rate");
if (enode != NULL && !string_to_int(enode->GetContent(), _frame_rate)) {
daeegg_cat.warning() << "Invalid integer in <frame_rate> tag: '" << enode->GetContent() << "'" << endl;
} } } }
// Now loop through the children
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>");
skeleton->set_table_type(EggTable::TT_table);
bundle->add_child(skeleton);
pset<float> 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<float>::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<float>::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<float>::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<FCDGeometrySpline*> (geometry->GetSpline()));
}
}
if (geometry->IsSpline()) {
process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
}
break; }
case FCDEntityInstance::CONTROLLER: {
// Add the dart tag and process the controller instance
parent->set_dart_type(EggGroup::DT_default);
process_controller(parent, (const FCDControllerInstance*) instance);
break; }
case FCDEntityInstance::MATERIAL:
// We don't process this directly, handled per-geometry instead.
break;
case FCDEntityInstance::SIMPLE: {
// Grab the entity and check it's type.
}
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<FCDGeometrySpline*> (geometry->GetSpline()));
}
}
// Add the joint hierarchy
#if FCOLLADA_VERSION < 0x00030005
FCDSceneNodeList roots = (const_cast<FCDControllerInstance*> (instance))->FindSkeletonNodes();
#else
FCDSceneNodeList roots;
(const_cast<FCDControllerInstance*> (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<int32, pvector<pair<PT_EggVertex, PN_stdfloat> > > influences;
if (vertex_pool) {
for (size_t in = 0; in < controller->GetSkinController()->GetInfluenceCount(); ++in) {
assert(vertex_pool->has_vertex(in));
for (size_t pa = 0; pa < controller->GetSkinController()->GetVertexInfluence(in)->GetPairCount(); ++pa) {
const FCDJointWeightPair* jwpair = controller->GetSkinController()->GetVertexInfluence(in)->GetPair(pa);
influences[jwpair->jointIndex].push_back(pair<PT_EggVertex, PN_stdfloat> (vertex_pool->get_vertex(in), jwpair->weight));
}
}
}
// Loop through the joints in the vertex influences
for (pmap<int32, pvector<pair<PT_EggVertex, PN_stdfloat> > >::iterator it = influences.begin(); it != influences.end(); ++it) {
if (it->first == -1) {
daeegg_cat.warning() << "Ignoring vertex influence with negative joint index\n";
//FIXME: Why are there joints with index -1
} else {
const string joint_id = FROM_FSTRING(controller->GetSkinController()->GetJoint(it->first)->GetId());
//TODO: what if the joints have just not been defined yet?
if (_joints.count(joint_id) > 0) {
if (_joints[joint_id]) {
for (pvector<pair<PT_EggVertex, PN_stdfloat> >::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 <Bundle> for the character and add it to the table
PT(DaeCharacter) character = new DaeCharacter(parent->get_name(), instance);
_table->add_child(character->as_egg_bundle());
}
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;
}
}

View File

@ -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 &copy);
~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<const string, PT(EggGroup)> _joints;
pmap<const string, PT(EggVertexPool)> _vertex_pools;
pvector<string> _skeletons;
int _frame_rate;
DaeCharacter::JointMap _joints;
typedef pvector<PT(DaeCharacter)> 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;
};

View File

@ -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);