mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
qpgeom animation
This commit is contained in:
parent
68a147ef62
commit
3716a4b470
@ -197,6 +197,7 @@ unify_attributes(EggPrimitive::Shading shading) {
|
||||
EggVertexPool *vertex_pool = orig_vertex->get_pool();
|
||||
nassertv(vertex_pool != (EggVertexPool *)NULL);
|
||||
vertex = vertex_pool->create_unique_vertex(*vertex);
|
||||
vertex->copy_grefs_from(*orig_vertex);
|
||||
replace(pi, vertex);
|
||||
}
|
||||
clear_normal();
|
||||
@ -225,6 +226,7 @@ unify_attributes(EggPrimitive::Shading shading) {
|
||||
EggVertexPool *vertex_pool = orig_vertex->get_pool();
|
||||
nassertv(vertex_pool != (EggVertexPool *)NULL);
|
||||
vertex = vertex_pool->create_unique_vertex(*vertex);
|
||||
vertex->copy_grefs_from(*orig_vertex);
|
||||
replace(pi, vertex);
|
||||
}
|
||||
}
|
||||
@ -272,6 +274,7 @@ unify_attributes(EggPrimitive::Shading shading) {
|
||||
EggVertexPool *vertex_pool = orig_vertex->get_pool();
|
||||
nassertv(vertex_pool != (EggVertexPool *)NULL);
|
||||
vertex = vertex_pool->create_unique_vertex(*vertex);
|
||||
vertex->copy_grefs_from(*orig_vertex);
|
||||
replace(pi, vertex);
|
||||
}
|
||||
Components::iterator ci;
|
||||
|
@ -944,7 +944,9 @@ rebuild_vertex_pool(EggVertexPool *vertex_pool, bool recurse) {
|
||||
Vertices::const_iterator vi;
|
||||
for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
|
||||
EggVertex *vertex = (*vi);
|
||||
prim->add_vertex(vertex_pool->create_unique_vertex(*vertex));
|
||||
EggVertex *new_vertex = vertex_pool->create_unique_vertex(*vertex);
|
||||
new_vertex->copy_grefs_from(*vertex);
|
||||
prim->add_vertex(new_vertex);
|
||||
}
|
||||
for (i = 0; i < num_components; i++) {
|
||||
prim->set_component(i, &attributes[i]);
|
||||
@ -965,7 +967,9 @@ rebuild_vertex_pool(EggVertexPool *vertex_pool, bool recurse) {
|
||||
Vertices::const_iterator vi;
|
||||
for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
|
||||
EggVertex *vertex = (*vi);
|
||||
prim->add_vertex(vertex_pool->create_unique_vertex(*vertex));
|
||||
EggVertex *new_vertex = vertex_pool->create_unique_vertex(*vertex);
|
||||
new_vertex->copy_grefs_from(*vertex);
|
||||
prim->add_vertex(new_vertex);
|
||||
}
|
||||
|
||||
} else if (child->is_of_type(EggGroupNode::get_class_type())) {
|
||||
|
@ -375,6 +375,7 @@ unify_attributes(EggPrimitive::Shading shading) {
|
||||
EggVertexPool *vertex_pool = orig_vertex->get_pool();
|
||||
nassertv(vertex_pool != (EggVertexPool *)NULL);
|
||||
vertex = vertex_pool->create_unique_vertex(*vertex);
|
||||
vertex->copy_grefs_from(*orig_vertex);
|
||||
replace(pi, vertex);
|
||||
}
|
||||
clear_normal();
|
||||
@ -406,6 +407,7 @@ unify_attributes(EggPrimitive::Shading shading) {
|
||||
EggVertexPool *vertex_pool = orig_vertex->get_pool();
|
||||
nassertv(vertex_pool != (EggVertexPool *)NULL);
|
||||
vertex = vertex_pool->create_unique_vertex(*vertex);
|
||||
vertex->copy_grefs_from(*orig_vertex);
|
||||
replace(pi, vertex);
|
||||
}
|
||||
}
|
||||
@ -1123,6 +1125,7 @@ do_apply_flat_attribute(int vertex_index, EggAttributes *attrib) {
|
||||
|
||||
if (significant_change) {
|
||||
new_vertex = get_pool()->create_unique_vertex(*new_vertex);
|
||||
new_vertex->copy_grefs_from(*orig_vertex);
|
||||
set_vertex(vertex_index, new_vertex);
|
||||
} else {
|
||||
// Just copy the new attributes back into the pool.
|
||||
|
@ -19,10 +19,11 @@
|
||||
#include "characterMaker.h"
|
||||
#include "eggLoader.h"
|
||||
#include "config_egg2pg.h"
|
||||
|
||||
#include "eggBinner.h"
|
||||
#include "computedVertices.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "eggBin.h"
|
||||
#include "partGroup.h"
|
||||
#include "characterJoint.h"
|
||||
#include "characterJointBundle.h"
|
||||
@ -32,6 +33,8 @@
|
||||
#include "eggSurface.h"
|
||||
#include "eggCurve.h"
|
||||
#include "modelNode.h"
|
||||
#include "jointVertexTransform.h"
|
||||
#include "userVertexTransform.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::Construtor
|
||||
@ -61,6 +64,15 @@ make_node() {
|
||||
return _character_node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::get_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the character.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string CharacterMaker::
|
||||
get_name() const {
|
||||
return _egg_root->get_name();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::egg_to_part
|
||||
@ -82,6 +94,38 @@ egg_to_part(EggNode *egg_node) const {
|
||||
return _parts[index];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::egg_to_transform
|
||||
// Access: Public
|
||||
// Description: Returns a JointVertexTransform suitable for
|
||||
// applying the animation associated with the given
|
||||
// egg node (which should be a joint). Returns an
|
||||
// identity transform if the egg node is not a joint in
|
||||
// the character's hierarchy.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VertexTransform *CharacterMaker::
|
||||
egg_to_transform(EggNode *egg_node) {
|
||||
int index = egg_to_index(egg_node);
|
||||
if (index < 0) {
|
||||
// Not a joint in the hierarchy.
|
||||
return get_identity_transform();
|
||||
}
|
||||
|
||||
VertexTransforms::iterator vi = _vertex_transforms.find(index);
|
||||
if (vi != _vertex_transforms.end()) {
|
||||
return (*vi).second;
|
||||
}
|
||||
|
||||
PartGroup *part = _parts[index];
|
||||
CharacterJoint *joint;
|
||||
DCAST_INTO_R(joint, part, get_identity_transform());
|
||||
|
||||
PT(VertexTransform) vt = new JointVertexTransform(joint);
|
||||
_vertex_transforms[index] = vt;
|
||||
|
||||
return vt;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::egg_to_index
|
||||
// Access: Public
|
||||
@ -148,12 +192,19 @@ make_bundle() {
|
||||
build_joint_hierarchy(_egg_root, _skeleton_root);
|
||||
_bundle->sort_descendants();
|
||||
|
||||
if (use_qpgeom) {
|
||||
// The new, experimental Geom system.
|
||||
make_qpgeometry(_egg_root);
|
||||
|
||||
} else {
|
||||
// The old Geom system.
|
||||
make_geometry(_egg_root);
|
||||
|
||||
_character_node->_computed_vertices =
|
||||
_comp_verts_maker.make_computed_vertices(_character_node, *this);
|
||||
}
|
||||
parent_joint_nodes(_skeleton_root);
|
||||
make_geometry(_egg_root);
|
||||
|
||||
_character_node->_computed_vertices =
|
||||
_comp_verts_maker.make_computed_vertices(_character_node, *this);
|
||||
|
||||
|
||||
return _bundle;
|
||||
}
|
||||
|
||||
@ -276,6 +327,57 @@ make_geometry(EggNode *egg_node) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::make_qpgeometry
|
||||
// Access: Private
|
||||
// Description: Walks the hierarchy, looking for bins that represent
|
||||
// polysets, which are to be animated with the
|
||||
// character. Invokes the egg loader to create the
|
||||
// animated geometry.
|
||||
//
|
||||
// This is part of the experimental Geom rewrite.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CharacterMaker::
|
||||
make_qpgeometry(EggNode *egg_node) {
|
||||
if (egg_node->is_of_type(EggBin::get_class_type())) {
|
||||
EggBin *egg_bin = DCAST(EggBin, egg_node);
|
||||
|
||||
if (!egg_bin->empty() &&
|
||||
egg_bin->get_bin_number() == EggBinner::BN_polyset) {
|
||||
EggGroupNode *bin_home = determine_bin_home(egg_bin);
|
||||
|
||||
bool is_dynamic;
|
||||
if (bin_home == (EggGroupNode *)NULL) {
|
||||
// This is a dynamic polyset that lives under the character's
|
||||
// root node.
|
||||
bin_home = _egg_root;
|
||||
is_dynamic = true;
|
||||
} else {
|
||||
// This is a totally static polyset that is parented under
|
||||
// some animated joint node.
|
||||
is_dynamic = false;
|
||||
}
|
||||
|
||||
PandaNode *parent = part_to_node(egg_to_part(bin_home));
|
||||
LMatrix4d transform =
|
||||
egg_bin->get_vertex_frame() *
|
||||
bin_home->get_node_frame_inv();
|
||||
|
||||
_loader.make_polyset(egg_bin, parent, &transform, is_dynamic,
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
|
||||
EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
|
||||
|
||||
EggGroupNode::const_iterator ci;
|
||||
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
|
||||
make_qpgeometry(*ci);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::make_static_primitive
|
||||
// Access: Private
|
||||
@ -419,3 +521,142 @@ determine_primitive_home(EggPrimitive *egg_primitive) {
|
||||
// explicit joint assignment.
|
||||
return home;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::determine_bin_home
|
||||
// Access: Private
|
||||
// Description: Examines the joint assignment of the vertices of all
|
||||
// of the primitives within this bin to determine which
|
||||
// parent node the bin's polyset should be created
|
||||
// under.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggGroupNode *CharacterMaker::
|
||||
determine_bin_home(EggBin *egg_bin) {
|
||||
// A primitive's vertices may be referenced by any joint in the
|
||||
// character. Or, the primitive itself may be explicitly placed
|
||||
// under a joint.
|
||||
|
||||
// If any of the vertices, in any primitive, are referenced by
|
||||
// multiple joints, or if any two vertices are referenced by
|
||||
// different joints, then the entire bin must be considered dynamic.
|
||||
// (We'll indicate a dynamic bin by returning NULL.)
|
||||
|
||||
// We need to keep track of the one joint we've encountered so far,
|
||||
// to see if all the vertices are referenced by the same joint.
|
||||
EggGroupNode *home = NULL;
|
||||
|
||||
EggGroupNode::const_iterator ci;
|
||||
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
||||
CPT(EggPrimitive) egg_primitive = DCAST(EggPrimitive, (*ci));
|
||||
|
||||
EggPrimitive::const_iterator vi;
|
||||
for (vi = egg_primitive->begin();
|
||||
vi != egg_primitive->end();
|
||||
++vi) {
|
||||
EggVertex *vertex = (*vi);
|
||||
if (vertex->gref_size() > 1) {
|
||||
// This vertex is referenced by multiple joints; the primitive
|
||||
// is dynamic.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!vertex->_dxyzs.empty() ||
|
||||
!vertex->_dnormals.empty() ||
|
||||
!vertex->_drgbas.empty()) {
|
||||
// This vertex has some morph slider definitions; therefore, the
|
||||
// primitive is dynamic.
|
||||
return NULL;
|
||||
}
|
||||
EggVertex::const_uv_iterator uvi;
|
||||
for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
|
||||
if (!(*uvi)->_duvs.empty()) {
|
||||
// Ditto: the vertex has some UV morphs; therefore the
|
||||
// primitive is dynamic.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EggGroupNode *vertex_home;
|
||||
|
||||
if (vertex->gref_size() == 0) {
|
||||
// This vertex is not referenced at all, which means it belongs
|
||||
// right where it is.
|
||||
vertex_home = egg_primitive->get_parent();
|
||||
} else {
|
||||
nassertr(vertex->gref_size() == 1, NULL);
|
||||
// This vertex is referenced exactly once.
|
||||
vertex_home = *vertex->gref_begin();
|
||||
}
|
||||
|
||||
if (home != NULL && home != vertex_home) {
|
||||
// Oops, two vertices are referenced by different joints! The
|
||||
// primitive is dynamic.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
home = vertex_home;
|
||||
}
|
||||
}
|
||||
|
||||
// This shouldn't be possible, unless there are no vertices--but we
|
||||
// eliminate invalid primitives before we begin, so all primitives
|
||||
// should have vertices, and all bins should have primitives.
|
||||
nassertr(home != NULL, NULL);
|
||||
|
||||
// So, all the vertices are assigned to the same group. This means
|
||||
// all the primitives in the bin belong entirely to one joint.
|
||||
|
||||
// If the group is not, in fact, a joint then we return the first
|
||||
// joint above the group.
|
||||
EggGroup *egg_group = (EggGroup *)NULL;
|
||||
if (home->is_of_type(EggGroup::get_class_type())) {
|
||||
egg_group = DCAST(EggGroup, home);
|
||||
}
|
||||
while (egg_group != (EggGroup *)NULL &&
|
||||
egg_group->get_group_type() != EggGroup::GT_joint &&
|
||||
egg_group->get_dart_type() == EggGroup::DT_none) {
|
||||
nassertr(egg_group->get_parent() != (EggGroupNode *)NULL, NULL);
|
||||
home = egg_group->get_parent();
|
||||
egg_group = (EggGroup *)NULL;
|
||||
if (home->is_of_type(EggGroup::get_class_type())) {
|
||||
egg_group = DCAST(EggGroup, home);
|
||||
}
|
||||
}
|
||||
|
||||
if (egg_group != (EggGroup *)NULL &&
|
||||
egg_group->get_group_type() == EggGroup::GT_joint &&
|
||||
egg_group->get_dcs_type() == EggGroup::DC_none) {
|
||||
// If we have rigid geometry that is assigned to a joint without a
|
||||
// <DCS> flag, which means the joint didn't get created as its own
|
||||
// node, go ahead and make an implicit <DCS> flag for the joint.
|
||||
|
||||
// The alternative is to return NULL to treat the geometry as
|
||||
// dynamic (and animate it by animating its vertices), but display
|
||||
// lists and vertex buffers will perform better if as much
|
||||
// geometry as possible is rigid.
|
||||
|
||||
egg_group->set_dcs_type(EggGroup::DC_default);
|
||||
PT(ModelNode) geom_node = new ModelNode(egg_group->get_name());
|
||||
geom_node->set_preserve_transform(ModelNode::PT_local);
|
||||
|
||||
CharacterJoint *joint;
|
||||
DCAST_INTO_R(joint, egg_to_part(egg_group), home);
|
||||
joint->_geom_node = geom_node.p();
|
||||
}
|
||||
|
||||
return home;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CharacterMaker::get_identity_transform
|
||||
// Access: Private
|
||||
// Description: Returns a VertexTransform that represents the root of
|
||||
// the character--it never animates.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VertexTransform *CharacterMaker::
|
||||
get_identity_transform() {
|
||||
if (_identity_transform == (VertexTransform *)NULL) {
|
||||
_identity_transform = new UserVertexTransform("root");
|
||||
}
|
||||
return _identity_transform;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "computedVerticesMaker.h"
|
||||
|
||||
#include "vertexTransform.h"
|
||||
#include "vector_PartGroupStar.h"
|
||||
#include "typedef.h"
|
||||
#include "pmap.h"
|
||||
@ -31,6 +31,7 @@ class EggNode;
|
||||
class EggGroup;
|
||||
class EggGroupNode;
|
||||
class EggPrimitive;
|
||||
class EggBin;
|
||||
class PartGroup;
|
||||
class CharacterJointBundle;
|
||||
class Character;
|
||||
@ -51,7 +52,9 @@ public:
|
||||
|
||||
Character *make_node();
|
||||
|
||||
string get_name() const;
|
||||
PartGroup *egg_to_part(EggNode *egg_node) const;
|
||||
VertexTransform *egg_to_transform(EggNode *egg_node);
|
||||
int egg_to_index(EggNode *egg_node) const;
|
||||
PandaNode *part_to_node(PartGroup *part) const;
|
||||
|
||||
@ -63,12 +66,15 @@ private:
|
||||
void parent_joint_nodes(PartGroup *part);
|
||||
|
||||
void make_geometry(EggNode *egg_node);
|
||||
void make_qpgeometry(EggNode *egg_node);
|
||||
|
||||
void make_static_primitive(EggPrimitive *egg_primitive,
|
||||
EggGroupNode *prim_home);
|
||||
void make_dynamic_primitive(EggPrimitive *egg_primitive,
|
||||
EggGroupNode *prim_home);
|
||||
EggGroupNode *determine_primitive_home(EggPrimitive *egg_primitive);
|
||||
EggGroupNode *determine_bin_home(EggBin *egg_bin);
|
||||
VertexTransform *get_identity_transform();
|
||||
|
||||
typedef pmap<EggNode *, int> NodeMap;
|
||||
NodeMap _node_map;
|
||||
@ -76,6 +82,10 @@ private:
|
||||
typedef vector_PartGroupStar Parts;
|
||||
Parts _parts;
|
||||
|
||||
typedef pmap<int, PT(VertexTransform) > VertexTransforms;
|
||||
VertexTransforms _vertex_transforms;
|
||||
PT(VertexTransform) _identity_transform;
|
||||
|
||||
EggLoader &_loader;
|
||||
EggGroup *_egg_root;
|
||||
Character *_character_node;
|
||||
|
@ -89,6 +89,8 @@
|
||||
#include "sheetNode.h"
|
||||
#include "look_at.h"
|
||||
#include "configVariableString.h"
|
||||
#include "transformBlendPalette.h"
|
||||
#include "transformBlend.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <algorithm>
|
||||
@ -527,6 +529,135 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent,
|
||||
_builder.add_prim(bucket, bprim);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggLoader::make_polyset
|
||||
// Access: Public
|
||||
// Description: Creates a polyset--that is, a Geom--from the
|
||||
// primitives that have already been grouped into a bin.
|
||||
// If transform is non-NULL, it represents the transform
|
||||
// to apply to the vertices (instead of the default
|
||||
// transform based on the bin's position within the
|
||||
// hierarchy).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggLoader::
|
||||
make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
|
||||
bool is_dynamic, CharacterMaker *character_maker) {
|
||||
if (egg_bin->empty()) {
|
||||
// If there are no children--no primitives--never mind.
|
||||
return;
|
||||
}
|
||||
|
||||
// We know that all of the primitives in the bin have the same
|
||||
// render state, so we can get that information from the first
|
||||
// primitive.
|
||||
EggGroupNode::const_iterator ci = egg_bin->begin();
|
||||
nassertv(ci != egg_bin->end());
|
||||
CPT(EggPrimitive) first_prim = DCAST(EggPrimitive, (*ci));
|
||||
nassertv(first_prim != (EggPrimitive *)NULL);
|
||||
const EggRenderState *render_state;
|
||||
DCAST_INTO_V(render_state, first_prim->get_user_data(EggRenderState::get_class_type()));
|
||||
|
||||
if (render_state->_hidden && egg_suppress_hidden) {
|
||||
// Eat this polyset.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!use_qpgeom) {
|
||||
// In the old Geom system, just send each primitive to the
|
||||
// Builder.
|
||||
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
||||
EggPrimitive *egg_prim;
|
||||
DCAST_INTO_V(egg_prim, (*ci));
|
||||
make_nonindexed_primitive(egg_prim, parent, transform, _comp_verts_maker);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate an optimal vertex pool for the polygons within just the
|
||||
// bin (which translates directly to an optimal GeomVertexData
|
||||
// structure).
|
||||
PT(EggVertexPool) vertex_pool = new EggVertexPool("bin");
|
||||
egg_bin->rebuild_vertex_pool(vertex_pool, false);
|
||||
|
||||
if (egg_mesh) {
|
||||
// If we're using the mesher, mesh now.
|
||||
egg_bin->mesh_triangles(0);
|
||||
|
||||
} else {
|
||||
// If we're not using the mesher, at least triangulate any
|
||||
// higher-order polygons we might have.
|
||||
egg_bin->triangulate_polygons(EggGroupNode::T_polygon | EggGroupNode::T_convex);
|
||||
}
|
||||
|
||||
// Now that we've meshed, apply the per-prim attributes onto the
|
||||
// vertices, so we can copy them to the GeomVertexData.
|
||||
egg_bin->apply_last_attribute(false);
|
||||
egg_bin->post_apply_flat_attribute(false);
|
||||
vertex_pool->remove_unused_vertices();
|
||||
|
||||
// vertex_pool->write(cerr, 0);
|
||||
// egg_bin->write(cerr, 0);
|
||||
|
||||
// Now create a handful of GeomPrimitives corresponding to the
|
||||
// various types of primitives we have.
|
||||
Primitives primitives;
|
||||
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
||||
EggPrimitive *egg_prim;
|
||||
DCAST_INTO_V(egg_prim, (*ci));
|
||||
make_primitive(render_state, egg_prim, primitives);
|
||||
}
|
||||
|
||||
if (!primitives.empty()) {
|
||||
LMatrix4d mat;
|
||||
if (transform != NULL) {
|
||||
mat = (*transform);
|
||||
} else {
|
||||
mat = egg_bin->get_vertex_to_node();
|
||||
}
|
||||
|
||||
// Now convert the vertex pool to a GeomVertexData.
|
||||
nassertv(vertex_pool != (EggVertexPool *)NULL);
|
||||
PT(qpGeomVertexData) vertex_data =
|
||||
make_vertex_data(render_state, vertex_pool, mat,
|
||||
is_dynamic, character_maker);
|
||||
nassertv(vertex_data != (qpGeomVertexData *)NULL);
|
||||
|
||||
// And create a Geom to hold the primitives.
|
||||
PT(qpGeom) geom = new qpGeom;
|
||||
geom->set_vertex_data(vertex_data);
|
||||
|
||||
// Add each new primitive to the Geom.
|
||||
Primitives::const_iterator pi;
|
||||
for (pi = primitives.begin(); pi != primitives.end(); ++pi) {
|
||||
qpGeomPrimitive *primitive = (*pi).second;
|
||||
geom->add_primitive(primitive);
|
||||
}
|
||||
|
||||
// vertex_data->write(cerr);
|
||||
// geom->write(cerr);
|
||||
// render_state->_state->write(cerr, 0);
|
||||
|
||||
// Now, is our parent node a GeomNode, or just an ordinary
|
||||
// PandaNode? If it's a GeomNode, we can add the new Geom directly
|
||||
// to our parent; otherwise, we need to create a new node.
|
||||
if (parent->is_geom_node() && !render_state->_hidden) {
|
||||
DCAST(GeomNode, parent)->add_geom(geom, render_state->_state);
|
||||
|
||||
} else {
|
||||
PT(GeomNode) geom_node = new GeomNode(egg_bin->get_name());
|
||||
if (render_state->_hidden) {
|
||||
parent->add_stashed(geom_node);
|
||||
} else {
|
||||
parent->add_child(geom_node);
|
||||
}
|
||||
geom_node->add_geom(geom, render_state->_state);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggLoader::make_nurbs_curve
|
||||
// Access: Private
|
||||
@ -1404,7 +1535,8 @@ make_node(EggBin *egg_bin, PandaNode *parent) {
|
||||
// node (a parent of one or more similar EggPrimitives).
|
||||
switch (egg_bin->get_bin_number()) {
|
||||
case EggBinner::BN_polyset:
|
||||
return make_polyset(egg_bin, parent);
|
||||
make_polyset(egg_bin, parent, NULL, false, NULL);
|
||||
return NULL;
|
||||
|
||||
case EggBinner::BN_lod:
|
||||
return make_lod(egg_bin, parent);
|
||||
@ -1417,122 +1549,6 @@ make_node(EggBin *egg_bin, PandaNode *parent) {
|
||||
return (PandaNode *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggLoader::make_polyset
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode *EggLoader::
|
||||
make_polyset(EggBin *egg_bin, PandaNode *parent) {
|
||||
if (egg_bin->empty()) {
|
||||
// If there are no children--no primitives--never mind.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// We know that all of the primitives in the bin have the same
|
||||
// render state, so we can get that information from the first
|
||||
// primitive.
|
||||
EggGroup::const_iterator ci = egg_bin->begin();
|
||||
nassertr(ci != egg_bin->end(), NULL);
|
||||
CPT(EggPrimitive) first_prim = DCAST(EggPrimitive, (*ci));
|
||||
nassertr(first_prim != (EggPrimitive *)NULL, NULL);
|
||||
const EggRenderState *render_state;
|
||||
DCAST_INTO_R(render_state, first_prim->get_user_data(EggRenderState::get_class_type()), NULL);
|
||||
|
||||
if (render_state->_hidden && egg_suppress_hidden) {
|
||||
// Eat this polyset.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!use_qpgeom) {
|
||||
// In the old Geom system, just send each primitive to the
|
||||
// Builder.
|
||||
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
||||
EggPrimitive *egg_prim;
|
||||
DCAST_INTO_R(egg_prim, (*ci), NULL);
|
||||
make_nonindexed_primitive(egg_prim, parent, NULL, _comp_verts_maker);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Generate an optimal vertex pool for the polygons within just the
|
||||
// bin (which translates directly to an optimal GeomVertexData
|
||||
// structure).
|
||||
PT(EggVertexPool) vertex_pool = new EggVertexPool("bin");
|
||||
egg_bin->rebuild_vertex_pool(vertex_pool, false);
|
||||
|
||||
if (egg_mesh) {
|
||||
// If we're using the mesher, mesh now.
|
||||
egg_bin->mesh_triangles(0);
|
||||
|
||||
} else {
|
||||
// If we're not using the mesher, at least triangulate any
|
||||
// higher-order polygons we might have.
|
||||
egg_bin->triangulate_polygons(EggGroupNode::T_polygon | EggGroupNode::T_convex);
|
||||
}
|
||||
|
||||
// Now that we've meshed, apply the per-prim attributes onto the
|
||||
// vertices, so we can copy them to the GeomVertexData.
|
||||
egg_bin->apply_last_attribute(false);
|
||||
egg_bin->post_apply_flat_attribute(false);
|
||||
vertex_pool->remove_unused_vertices();
|
||||
|
||||
// vertex_pool->write(cerr, 0);
|
||||
// egg_bin->write(cerr, 0);
|
||||
|
||||
// Now create a handful of GeomPrimitives corresponding to the
|
||||
// various types of primitives we have.
|
||||
Primitives primitives;
|
||||
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
||||
EggPrimitive *egg_prim;
|
||||
DCAST_INTO_R(egg_prim, (*ci), NULL);
|
||||
make_primitive(render_state, egg_prim, primitives);
|
||||
}
|
||||
|
||||
if (!primitives.empty()) {
|
||||
// Now convert the vertex pool to a GeomVertexData.
|
||||
nassertr(vertex_pool != (EggVertexPool *)NULL, NULL);
|
||||
PT(qpGeomVertexData) vertex_data =
|
||||
make_vertex_data(render_state, vertex_pool,
|
||||
egg_bin->get_vertex_to_node());
|
||||
nassertr(vertex_data != (qpGeomVertexData *)NULL, NULL);
|
||||
|
||||
// And create a Geom to hold the primitives.
|
||||
PT(qpGeom) geom = new qpGeom;
|
||||
geom->set_vertex_data(vertex_data);
|
||||
|
||||
// Add each new primitive to the Geom.
|
||||
Primitives::const_iterator pi;
|
||||
for (pi = primitives.begin(); pi != primitives.end(); ++pi) {
|
||||
qpGeomPrimitive *primitive = (*pi).second;
|
||||
geom->add_primitive(primitive);
|
||||
}
|
||||
|
||||
// vertex_data->write(cerr);
|
||||
// geom->write(cerr);
|
||||
// render_state->_state->write(cerr, 0);
|
||||
|
||||
// Now, is our parent node a GeomNode, or just an ordinary
|
||||
// PandaNode? If it's a GeomNode, we can add the new Geom directly
|
||||
// to our parent; otherwise, we need to create a new node.
|
||||
if (parent->is_geom_node() && !render_state->_hidden) {
|
||||
DCAST(GeomNode, parent)->add_geom(geom, render_state->_state);
|
||||
|
||||
} else {
|
||||
PT(GeomNode) geom_node = new GeomNode(egg_bin->get_name());
|
||||
if (render_state->_hidden) {
|
||||
parent->add_stashed(geom_node);
|
||||
} else {
|
||||
parent->add_child(geom_node);
|
||||
}
|
||||
geom_node->add_geom(geom, render_state->_state);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggLoader::make_lod
|
||||
// Access: Private
|
||||
@ -1888,7 +1904,8 @@ check_for_polysets(EggGroup *egg_group, bool &all_polysets, bool &any_hidden) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(qpGeomVertexData) EggLoader::
|
||||
make_vertex_data(const EggRenderState *render_state,
|
||||
EggVertexPool *vertex_pool, const LMatrix4d &transform) {
|
||||
EggVertexPool *vertex_pool, const LMatrix4d &transform,
|
||||
bool is_dynamic, CharacterMaker *character_maker) {
|
||||
VertexPoolTransform vpt;
|
||||
vpt._vertex_pool = vertex_pool;
|
||||
vpt._bake_in_uvs = render_state->_bake_in_uvs;
|
||||
@ -1928,12 +1945,39 @@ make_vertex_data(const EggRenderState *render_state,
|
||||
array_format->add_data_type(iname, 2, qpGeomVertexDataType::NT_float32);
|
||||
}
|
||||
|
||||
CPT(qpGeomVertexFormat) format =
|
||||
qpGeomVertexFormat::register_format(new qpGeomVertexFormat(array_format));
|
||||
PT(qpGeomVertexFormat) temp_format = new qpGeomVertexFormat(array_format);
|
||||
|
||||
// Now create a new GeomVertexData using the indicated format.
|
||||
PT(qpGeomVertexData) vertex_data =
|
||||
new qpGeomVertexData(format, qpGeomUsageHint::UH_static);
|
||||
PT(TransformBlendPalette) blend_palette;
|
||||
string name;
|
||||
|
||||
if (is_dynamic) {
|
||||
// If it's a dynamic object, we need a TransformBlendPalette, and
|
||||
// another array that indexes into the palette per vertex.
|
||||
blend_palette = new TransformBlendPalette;
|
||||
PT(qpGeomVertexArrayFormat) blend_array_format = new qpGeomVertexArrayFormat;
|
||||
blend_array_format->add_data_type
|
||||
(InternalName::get_transform_blend(), 1, qpGeomVertexDataType::NT_uint16);
|
||||
temp_format->add_array(blend_array_format);
|
||||
|
||||
// We'll also assign the character name to the vertex data, so it
|
||||
// will show up in PStats.
|
||||
name = character_maker->get_name();
|
||||
}
|
||||
|
||||
CPT(qpGeomVertexFormat) format =
|
||||
qpGeomVertexFormat::register_format(temp_format);
|
||||
|
||||
// Now create a new GeomVertexData using the indicated format. It
|
||||
// is actually correct to create it with UH_static even it
|
||||
// represents a dynamic object, because the vertex data itself won't
|
||||
// be changing--just the result of applying the animation is
|
||||
// dynamic.
|
||||
PT(qpGeomVertexData) vertex_data =
|
||||
new qpGeomVertexData(name, format, qpGeomUsageHint::UH_static);
|
||||
|
||||
if (is_dynamic) {
|
||||
vertex_data->set_transform_blend_palette(blend_palette);
|
||||
}
|
||||
|
||||
// And fill the data from the vertex pool.
|
||||
EggVertexPool::const_iterator vi;
|
||||
@ -1975,6 +2019,25 @@ make_vertex_data(const EggRenderState *render_state,
|
||||
|
||||
gvi.set_data2f(LCAST(float, uv));
|
||||
}
|
||||
|
||||
if (is_dynamic) {
|
||||
// Figure out the transforms affecting this particular vertex.
|
||||
TransformBlend blend;
|
||||
EggVertex::GroupRef::const_iterator gri;
|
||||
for (gri = vertex->gref_begin(); gri != vertex->gref_end(); ++gri) {
|
||||
EggGroup *egg_joint = (*gri);
|
||||
double membership = egg_joint->get_vertex_membership(vertex);
|
||||
|
||||
PT(VertexTransform) vt = character_maker->egg_to_transform(egg_joint);
|
||||
nassertr(vt != (VertexTransform *)NULL, vertex_data);
|
||||
blend.add_transform(vt, membership);
|
||||
}
|
||||
blend.normalize_weights();
|
||||
|
||||
int palette_index = blend_palette->add_blend(blend);
|
||||
gvi.set_data_type(InternalName::get_transform_blend());
|
||||
gvi.set_data1i(palette_index);
|
||||
}
|
||||
}
|
||||
|
||||
bool inserted = _vertex_pool_data.insert
|
||||
|
@ -58,6 +58,7 @@ class CollisionPolygon;
|
||||
class PortalNode;
|
||||
class PolylightNode;
|
||||
class EggRenderState;
|
||||
class CharacterMaker;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : EggLoader
|
||||
@ -83,6 +84,10 @@ public:
|
||||
const LMatrix4d *transform,
|
||||
ComputedVerticesMaker &comp_verts_maker);
|
||||
|
||||
void make_polyset(EggBin *egg_bin, PandaNode *parent,
|
||||
const LMatrix4d *transform, bool is_dynamic,
|
||||
CharacterMaker *character_maker);
|
||||
|
||||
private:
|
||||
class TextureDef {
|
||||
public:
|
||||
@ -137,9 +142,10 @@ private:
|
||||
|
||||
void check_for_polysets(EggGroup *egg_group, bool &all_polysets,
|
||||
bool &any_hidden);
|
||||
PT(qpGeomVertexData) make_vertex_data(const EggRenderState *render_state,
|
||||
EggVertexPool *vertex_pool,
|
||||
const LMatrix4d &transform);
|
||||
PT(qpGeomVertexData) make_vertex_data
|
||||
(const EggRenderState *render_state, EggVertexPool *vertex_pool,
|
||||
const LMatrix4d &transform, bool is_dynamic,
|
||||
CharacterMaker *character_maker);
|
||||
void make_primitive(const EggRenderState *render_state,
|
||||
EggPrimitive *egg_prim, Primitives &primitives);
|
||||
|
||||
|
@ -633,7 +633,7 @@ load_default_model(const NodePath &parent) {
|
||||
if (use_qpgeom) {
|
||||
// New, experimental Geom code.
|
||||
PT(qpGeomVertexData) vdata = new qpGeomVertexData
|
||||
(qpGeomVertexFormat::get_v3n3cpt2(),
|
||||
(string(), qpGeomVertexFormat::get_v3n3cpt2(),
|
||||
qpGeomUsageHint::UH_static);
|
||||
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
|
||||
qpGeomVertexIterator normal(vdata, InternalName::get_normal());
|
||||
@ -1060,7 +1060,7 @@ load_image_as_model(const Filename &filename) {
|
||||
|
||||
if (use_qpgeom) {
|
||||
PT(qpGeomVertexData) vdata = new qpGeomVertexData
|
||||
(qpGeomVertexFormat::get_v3t2(),
|
||||
(string(), qpGeomVertexFormat::get_v3t2(),
|
||||
qpGeomUsageHint::UH_static);
|
||||
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
|
||||
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
|
||||
|
@ -17,6 +17,30 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::get_name
|
||||
// Access: Published
|
||||
// Description: Returns the name passed to the constructor, if any.
|
||||
// This name is reported on the PStats graph for vertex
|
||||
// computations.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &qpGeomVertexData::
|
||||
get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::set_name
|
||||
// Access: Published
|
||||
// Description: Changes the name of the vertex data. This name is
|
||||
// reported on the PStats graph for vertex computations.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexData::
|
||||
set_name(const string &name) {
|
||||
_name = name;
|
||||
_this_animate_vertices_pcollector = PStatCollector(_animate_vertices_pcollector, name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::get_format
|
||||
// Access: Published
|
||||
@ -154,8 +178,8 @@ INLINE qpGeomVertexData::CData::
|
||||
CData(const qpGeomVertexData::CData ©) :
|
||||
_arrays(copy._arrays),
|
||||
_transform_blend_palette(copy._transform_blend_palette),
|
||||
_computed_vertices(copy._computed_vertices),
|
||||
_computed_vertices_modified(copy._computed_vertices_modified),
|
||||
_animated_vertices(copy._animated_vertices),
|
||||
_animated_vertices_modified(copy._animated_vertices_modified),
|
||||
_modified(copy._modified)
|
||||
{
|
||||
}
|
||||
|
@ -22,13 +22,14 @@
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "pset.h"
|
||||
#include "indent.h"
|
||||
|
||||
TypeHandle qpGeomVertexData::_type_handle;
|
||||
|
||||
PStatCollector qpGeomVertexData::_convert_pcollector("Cull:Munge:Convert");
|
||||
PStatCollector qpGeomVertexData::_scale_color_pcollector("Cull:Munge:Scale color");
|
||||
PStatCollector qpGeomVertexData::_set_color_pcollector("Cull:Munge:Set color");
|
||||
PStatCollector qpGeomVertexData::_compute_vertices_pcollector("Cull:Compute vertices");
|
||||
PStatCollector qpGeomVertexData::_animate_vertices_pcollector("Cull:Animate vertices");
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::Default Constructor
|
||||
@ -37,7 +38,9 @@ PStatCollector qpGeomVertexData::_compute_vertices_pcollector("Cull:Compute vert
|
||||
// reading from the bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpGeomVertexData::
|
||||
qpGeomVertexData() {
|
||||
qpGeomVertexData() :
|
||||
_this_animate_vertices_pcollector(_animate_vertices_pcollector)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -46,10 +49,13 @@ qpGeomVertexData() {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpGeomVertexData::
|
||||
qpGeomVertexData(const qpGeomVertexFormat *format,
|
||||
qpGeomVertexData(const string &name,
|
||||
const qpGeomVertexFormat *format,
|
||||
qpGeomUsageHint::UsageHint usage_hint) :
|
||||
_name(name),
|
||||
_format(format),
|
||||
_usage_hint(usage_hint)
|
||||
_usage_hint(usage_hint),
|
||||
_this_animate_vertices_pcollector(_animate_vertices_pcollector, name)
|
||||
{
|
||||
nassertv(_format->is_registered());
|
||||
|
||||
@ -72,8 +78,10 @@ qpGeomVertexData(const qpGeomVertexFormat *format,
|
||||
qpGeomVertexData::
|
||||
qpGeomVertexData(const qpGeomVertexData ©) :
|
||||
TypedWritableReferenceCount(copy),
|
||||
_name(copy._name),
|
||||
_format(copy._format),
|
||||
_cycler(copy._cycler)
|
||||
_cycler(copy._cycler),
|
||||
_this_animate_vertices_pcollector(copy._this_animate_vertices_pcollector)
|
||||
{
|
||||
}
|
||||
|
||||
@ -85,8 +93,10 @@ qpGeomVertexData(const qpGeomVertexData ©) :
|
||||
void qpGeomVertexData::
|
||||
operator = (const qpGeomVertexData ©) {
|
||||
TypedWritableReferenceCount::operator = (copy);
|
||||
_name = copy._name;
|
||||
_format = copy._format;
|
||||
_cycler = copy._cycler;
|
||||
_this_animate_vertices_pcollector = copy._this_animate_vertices_pcollector;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -138,7 +148,7 @@ clear_vertices() {
|
||||
(*ai)->clear_vertices();
|
||||
}
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_computed_vertices.clear();
|
||||
cdata->_animated_vertices.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -162,7 +172,7 @@ modify_array(int i) {
|
||||
cdata->_arrays[i] = new qpGeomVertexArrayData(*cdata->_arrays[i]);
|
||||
}
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_computed_vertices_modified = UpdateSeq();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
|
||||
return cdata->_arrays[i];
|
||||
}
|
||||
@ -181,7 +191,7 @@ set_array(int i, const qpGeomVertexArrayData *array) {
|
||||
nassertv(i >= 0 && i < (int)cdata->_arrays.size());
|
||||
cdata->_arrays[i] = (qpGeomVertexArrayData *)array;
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_computed_vertices_modified = UpdateSeq();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -203,7 +213,7 @@ modify_transform_blend_palette() {
|
||||
cdata->_transform_blend_palette = new TransformBlendPalette(*cdata->_transform_blend_palette);
|
||||
}
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_computed_vertices_modified = UpdateSeq();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
|
||||
return cdata->_transform_blend_palette;
|
||||
}
|
||||
@ -222,7 +232,7 @@ set_transform_blend_palette(const TransformBlendPalette *palette) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_transform_blend_palette = (TransformBlendPalette *)palette;
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_computed_vertices_modified = UpdateSeq();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -270,7 +280,7 @@ convert_to(const qpGeomVertexFormat *new_format) const {
|
||||
PStatTimer timer(_convert_pcollector);
|
||||
|
||||
PT(qpGeomVertexData) new_data =
|
||||
new qpGeomVertexData(new_format, get_usage_hint());
|
||||
new qpGeomVertexData(get_name(), new_format, get_usage_hint());
|
||||
new_data->set_transform_blend_palette(get_transform_blend_palette());
|
||||
|
||||
pset<int> done_arrays;
|
||||
@ -420,7 +430,7 @@ set_color(const Colorf &color, int num_components,
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::compute_vertices
|
||||
// Function: qpGeomVertexData::animate_vertices
|
||||
// Access: Published
|
||||
// Description: Returns a GeomVertexData that represents the results
|
||||
// of computing the vertex animation on the CPU for this
|
||||
@ -438,27 +448,27 @@ set_color(const Colorf &color, int num_components,
|
||||
// graphics backend to update vertex buffers optimally).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(qpGeomVertexData) qpGeomVertexData::
|
||||
compute_vertices() const {
|
||||
animate_vertices() const {
|
||||
CDReader cdata(_cycler);
|
||||
if (cdata->_transform_blend_palette == (TransformBlendPalette *)NULL) {
|
||||
// No vertex animation.
|
||||
return this;
|
||||
}
|
||||
|
||||
if (cdata->_computed_vertices == (qpGeomVertexData *)NULL) {
|
||||
if (cdata->_animated_vertices == (qpGeomVertexData *)NULL) {
|
||||
CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata);
|
||||
((qpGeomVertexData *)this)->make_computed_vertices(cdataw);
|
||||
return cdataw->_computed_vertices;
|
||||
((qpGeomVertexData *)this)->make_animated_vertices(cdataw);
|
||||
return cdataw->_animated_vertices;
|
||||
} else {
|
||||
UpdateSeq blend_modified = cdata->_transform_blend_palette->get_modified();
|
||||
if (cdata->_computed_vertices_modified == blend_modified) {
|
||||
if (cdata->_animated_vertices_modified == blend_modified) {
|
||||
// No changes.
|
||||
return cdata->_computed_vertices;
|
||||
return cdata->_animated_vertices;
|
||||
}
|
||||
CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata);
|
||||
cdataw->_computed_vertices_modified = blend_modified;
|
||||
((qpGeomVertexData *)this)->update_computed_vertices(cdataw);
|
||||
return cdataw->_computed_vertices;
|
||||
cdataw->_animated_vertices_modified = blend_modified;
|
||||
((qpGeomVertexData *)this)->update_animated_vertices(cdataw);
|
||||
return cdataw->_animated_vertices;
|
||||
}
|
||||
}
|
||||
|
||||
@ -510,7 +520,8 @@ replace_data_type(const InternalName *name, int num_components,
|
||||
}
|
||||
|
||||
PT(qpGeomVertexData) new_data =
|
||||
new qpGeomVertexData(qpGeomVertexFormat::register_format(new_format),
|
||||
new qpGeomVertexData(get_name(),
|
||||
qpGeomVertexFormat::register_format(new_format),
|
||||
usage_hint);
|
||||
if (keep_animation) {
|
||||
new_data->set_transform_blend_palette(get_transform_blend_palette());
|
||||
@ -567,6 +578,11 @@ output(ostream &out) const {
|
||||
void qpGeomVertexData::
|
||||
write(ostream &out, int indent_level) const {
|
||||
_format->write_with_data(out, indent_level, this);
|
||||
if (get_transform_blend_palette() != (TransformBlendPalette *)NULL) {
|
||||
indent(out, indent_level)
|
||||
<< "Transform blend palette:\n";
|
||||
get_transform_blend_palette()->write(out, indent_level + 2);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1155,63 +1171,80 @@ do_set_num_vertices(int n, qpGeomVertexData::CDWriter &cdata) {
|
||||
|
||||
if (any_changed) {
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_computed_vertices.clear();
|
||||
cdata->_animated_vertices.clear();
|
||||
}
|
||||
|
||||
return any_changed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::make_computed_vertices
|
||||
// Function: qpGeomVertexData::make_animated_vertices
|
||||
// Access: Private
|
||||
// Description: Creates the GeomVertexData that represents the
|
||||
// results of computing the vertex animation on the CPU.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexData::
|
||||
make_computed_vertices(qpGeomVertexData::CDWriter &cdata) {
|
||||
make_animated_vertices(qpGeomVertexData::CDWriter &cdata) {
|
||||
// First, make a new format that doesn't have the transform_blend
|
||||
// array.
|
||||
cdata->_computed_vertices = replace_data_type
|
||||
cdata->_animated_vertices = replace_data_type
|
||||
(InternalName::get_transform_blend(), 0, qpGeomVertexDataType::NT_uint16,
|
||||
min(get_usage_hint(), qpGeomUsageHint::UH_dynamic), false);
|
||||
|
||||
// Now fill it up with the appropriate data.
|
||||
update_computed_vertices(cdata);
|
||||
update_animated_vertices(cdata);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::update_computed_vertices
|
||||
// Function: qpGeomVertexData::update_animated_vertices
|
||||
// Access: Private
|
||||
// Description: Recomputes the results of computing the vertex
|
||||
// animation on the CPU, and applies them to the
|
||||
// existing computed_vertices object.
|
||||
// existing animated_vertices object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexData::
|
||||
update_computed_vertices(qpGeomVertexData::CDWriter &cdata) {
|
||||
update_animated_vertices(qpGeomVertexData::CDWriter &cdata) {
|
||||
int num_vertices = get_num_vertices();
|
||||
|
||||
if (gobj_cat.is_debug()) {
|
||||
gobj_cat.debug()
|
||||
<< "Computing " << num_vertices << " vertices.\n";
|
||||
<< "Animating " << num_vertices << " vertices for " << get_name()
|
||||
<< "\n";
|
||||
}
|
||||
PStatTimer timer(_compute_vertices_pcollector);
|
||||
|
||||
PStatTimer timer(_this_animate_vertices_pcollector);
|
||||
|
||||
CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette;
|
||||
nassertv(palette != (TransformBlendPalette *)NULL);
|
||||
PT(qpGeomVertexData) new_data = cdata->_computed_vertices;
|
||||
|
||||
// Recompute all the blends up front.
|
||||
int num_blends = palette->get_num_blends();
|
||||
int bi;
|
||||
for (bi = 0; bi < num_blends; bi++) {
|
||||
palette->get_blend(bi).update_blend();
|
||||
}
|
||||
|
||||
PT(qpGeomVertexData) new_data = cdata->_animated_vertices;
|
||||
|
||||
// Now go through and apply the scale, copying it to the new data.
|
||||
qpGeomVertexIterator from(this, InternalName::get_vertex());
|
||||
qpGeomVertexIterator blendi(this, InternalName::get_transform_blend());
|
||||
qpGeomVertexIterator to(new_data, InternalName::get_vertex());
|
||||
|
||||
for (int i = 0; i < num_vertices; i++) {
|
||||
LPoint4f vertex = from.get_data4f();
|
||||
int bi = blendi.get_data1i();
|
||||
const TransformBlend &blend = palette->get_blend(bi);
|
||||
blend.transform_point(vertex);
|
||||
|
||||
to.set_data4f(vertex);
|
||||
if (from.get_data_type()->get_num_values() == 4) {
|
||||
for (int i = 0; i < num_vertices; i++) {
|
||||
LPoint4f vertex = from.get_data4f();
|
||||
int bi = blendi.get_data1i();
|
||||
palette->get_blend(bi).transform_point(vertex);
|
||||
to.set_data4f(vertex);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num_vertices; i++) {
|
||||
LPoint3f vertex = from.get_data3f();
|
||||
int bi = blendi.get_data1i();
|
||||
palette->get_blend(bi).transform_point(vertex);
|
||||
to.set_data3f(vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,12 +64,16 @@ class EXPCL_PANDA qpGeomVertexData : public TypedWritableReferenceCount {
|
||||
private:
|
||||
qpGeomVertexData();
|
||||
PUBLISHED:
|
||||
qpGeomVertexData(const qpGeomVertexFormat *format,
|
||||
qpGeomVertexData(const string &name,
|
||||
const qpGeomVertexFormat *format,
|
||||
qpGeomUsageHint::UsageHint usage_hint);
|
||||
qpGeomVertexData(const qpGeomVertexData ©);
|
||||
void operator = (const qpGeomVertexData ©);
|
||||
virtual ~qpGeomVertexData();
|
||||
|
||||
INLINE const string &get_name() const;
|
||||
INLINE void set_name(const string &name);
|
||||
|
||||
INLINE const qpGeomVertexFormat *get_format() const;
|
||||
INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
|
||||
|
||||
@ -98,7 +102,7 @@ PUBLISHED:
|
||||
set_color(const Colorf &color, int num_components,
|
||||
qpGeomVertexDataType::NumericType numeric_type) const;
|
||||
|
||||
CPT(qpGeomVertexData) compute_vertices() const;
|
||||
CPT(qpGeomVertexData) animate_vertices() const;
|
||||
|
||||
PT(qpGeomVertexData)
|
||||
replace_data_type(const InternalName *name, int num_components,
|
||||
@ -135,6 +139,7 @@ public:
|
||||
static void unpack_argb(int data[4], unsigned int packed_argb);
|
||||
|
||||
private:
|
||||
string _name;
|
||||
CPT(qpGeomVertexFormat) _format;
|
||||
qpGeomUsageHint::UsageHint _usage_hint;
|
||||
|
||||
@ -152,8 +157,8 @@ private:
|
||||
|
||||
Arrays _arrays;
|
||||
PT(TransformBlendPalette) _transform_blend_palette;
|
||||
PT(qpGeomVertexData) _computed_vertices;
|
||||
UpdateSeq _computed_vertices_modified;
|
||||
PT(qpGeomVertexData) _animated_vertices;
|
||||
UpdateSeq _animated_vertices_modified;
|
||||
UpdateSeq _modified;
|
||||
};
|
||||
|
||||
@ -163,13 +168,15 @@ private:
|
||||
|
||||
private:
|
||||
bool do_set_num_vertices(int n, CDWriter &cdata);
|
||||
void make_computed_vertices(CDWriter &cdata);
|
||||
void update_computed_vertices(CDWriter &cdata);
|
||||
void make_animated_vertices(CDWriter &cdata);
|
||||
void update_animated_vertices(CDWriter &cdata);
|
||||
|
||||
static PStatCollector _convert_pcollector;
|
||||
static PStatCollector _scale_color_pcollector;
|
||||
static PStatCollector _set_color_pcollector;
|
||||
static PStatCollector _compute_vertices_pcollector;
|
||||
static PStatCollector _animate_vertices_pcollector;
|
||||
|
||||
PStatCollector _this_animate_vertices_pcollector;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
@ -177,22 +177,53 @@ get_weight(int n) const {
|
||||
return _entries[n]._weight;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformBlend::update_blend
|
||||
// Access: Published
|
||||
// Description: Recomputes the internal representation of the blend
|
||||
// value, if necessary. You should call this before
|
||||
// calling get_blend() or transform_point().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TransformBlend::
|
||||
update_blend() const {
|
||||
CDReader cdata(_cycler);
|
||||
if (cdata->_global_modified != VertexTransform::get_global_modified()) {
|
||||
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata);
|
||||
((TransformBlend *)this)->recompute_result(cdataw);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformBlend::get_blend
|
||||
// Access: Published
|
||||
// Description: Returns the current value of the blend, based on the
|
||||
// current value of all of the nested transform objects
|
||||
// and their associated weights.
|
||||
//
|
||||
// You should call update_blend() to ensure that the
|
||||
// cache is up-to-date before calling this.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TransformBlend::
|
||||
get_blend(LMatrix4f &result) const {
|
||||
CDReader cdata(_cycler);
|
||||
if (cdata->_global_modified != VertexTransform::get_global_modified()) {
|
||||
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata);
|
||||
((TransformBlend *)this)->recompute_result(cdataw);
|
||||
result = cdataw->_result;
|
||||
} else {
|
||||
result = cdata->_result;
|
||||
nassertv(cdata->_global_modified == VertexTransform::get_global_modified());
|
||||
result = cdata->_result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformBlend::transform_point
|
||||
// Access: Published
|
||||
// Description: Transforms the indicated point by the blend matrix.
|
||||
//
|
||||
// You should call update_blend() to ensure that the
|
||||
// cache is up-to-date before calling this.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TransformBlend::
|
||||
transform_point(LPoint4f &point) const {
|
||||
if (!_entries.empty()) {
|
||||
CDReader cdata(_cycler);
|
||||
nassertv(cdata->_global_modified == VertexTransform::get_global_modified());
|
||||
point = point * cdata->_result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,18 +231,16 @@ get_blend(LMatrix4f &result) const {
|
||||
// Function: TransformBlend::transform_point
|
||||
// Access: Published
|
||||
// Description: Transforms the indicated point by the blend matrix.
|
||||
//
|
||||
// You should call update_blend() to ensure that the
|
||||
// cache is up-to-date before calling this.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TransformBlend::
|
||||
transform_point(LPoint4f &point) const {
|
||||
transform_point(LPoint3f &point) const {
|
||||
if (!_entries.empty()) {
|
||||
CDReader cdata(_cycler);
|
||||
if (cdata->_global_modified != VertexTransform::get_global_modified()) {
|
||||
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata);
|
||||
((TransformBlend *)this)->recompute_result(cdataw);
|
||||
point = point * cdataw->_result;
|
||||
} else {
|
||||
point = point * cdata->_result;
|
||||
}
|
||||
nassertv(cdata->_global_modified == VertexTransform::get_global_modified());
|
||||
point = point * cdata->_result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,11 @@ PUBLISHED:
|
||||
INLINE const VertexTransform *get_transform(int n) const;
|
||||
INLINE float get_weight(int n) const;
|
||||
|
||||
INLINE void update_blend() const;
|
||||
|
||||
INLINE void get_blend(LMatrix4f &result) const;
|
||||
INLINE void transform_point(LPoint4f &point) const;
|
||||
INLINE void transform_point(LPoint3f &point) const;
|
||||
INLINE UpdateSeq get_modified() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
@ -119,9 +119,10 @@ add_blend(const TransformBlend &blend) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TransformBlendPalette::
|
||||
write(ostream &out) const {
|
||||
write(ostream &out, int indent_level) const {
|
||||
for (int i = 0; i < (int)_blends.size(); i++) {
|
||||
out << i << ". " << _blends[i] << "\n";
|
||||
indent(out, indent_level)
|
||||
<< i << ". " << _blends[i] << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ PUBLISHED:
|
||||
void remove_blend(int n);
|
||||
int add_blend(const TransformBlend &blend);
|
||||
|
||||
void write(ostream &out) const;
|
||||
void write(ostream &out, int indent_level) const;
|
||||
|
||||
private:
|
||||
void clear_index();
|
||||
|
@ -38,7 +38,7 @@ munge_geom(const qpGeomMunger *munger) {
|
||||
_munger = munger;
|
||||
CPT(qpGeom) qpgeom = DCAST(qpGeom, _geom);
|
||||
qpgeom->munge_geom(munger, qpgeom, _munged_data);
|
||||
_munged_data = _munged_data->compute_vertices();
|
||||
_munged_data = _munged_data->animate_vertices();
|
||||
_geom = qpgeom;
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,7 @@ static TimeCollectorProperties time_properties[] = {
|
||||
{ 0, "App:Show code:Nametags:3d:Contents", { 0.0, 0.5, 0.0 } },
|
||||
{ 0, "App:Show code:Nametags:3d:Adjust", { 0.5, 0.0, 0.5 } },
|
||||
{ 1, "Cull", { 0.0, 1.0, 0.0 }, 1.0 / 30.0 },
|
||||
{ 1, "Cull:Animate vertices", { 1.0, 0.5, 0.3 }, 1.0 / 30.0 },
|
||||
{ 1, "Cull:Show fps", { 0.5, 0.8, 1.0 } },
|
||||
{ 1, "Cull:Bins", { 0.3, 0.6, 0.3 } },
|
||||
{ 1, "Cull:Munge", { 0.3, 0.3, 0.9 } },
|
||||
|
Loading…
x
Reference in New Issue
Block a user