mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
extract skinning information for NURBS surfaces
This commit is contained in:
parent
9089fa3820
commit
0b15f7a14b
@ -70,6 +70,7 @@
|
||||
#include <maya/MAnimUtil.h>
|
||||
#include <maya/MFnSkinCluster.h>
|
||||
#include <maya/MFnSingleIndexedComponent.h>
|
||||
#include <maya/MFnDoubleIndexedComponent.h>
|
||||
#include <maya/MItDependencyGraph.h>
|
||||
#include <maya/MDagPathArray.h>
|
||||
#include <maya/MSelectionList.h>
|
||||
@ -1033,11 +1034,8 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
We don't use these variables currently.
|
||||
MFnNurbsSurface::Form u_form = surface.formInU();
|
||||
MFnNurbsSurface::Form v_form = surface.formInV();
|
||||
*/
|
||||
|
||||
int u_degree = surface.degreeU();
|
||||
int v_degree = surface.degreeV();
|
||||
@ -1045,6 +1043,11 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
int u_cvs = surface.numCVsInU();
|
||||
int v_cvs = surface.numCVsInV();
|
||||
|
||||
// Maya repeats CVS at the end for a periodic surface, and doesn't
|
||||
// count them in the weighted array, below.
|
||||
int maya_u_cvs = (u_form == MFnNurbsSurface::kPeriodic) ? u_cvs - u_degree : u_cvs;
|
||||
int maya_v_cvs = (v_form == MFnNurbsSurface::kPeriodic) ? v_cvs - v_degree : v_cvs;
|
||||
|
||||
int u_knots = surface.numKnotsInU();
|
||||
int v_knots = surface.numKnotsInV();
|
||||
|
||||
@ -1084,11 +1087,12 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
if (!status) {
|
||||
status.perror("MPoint::get");
|
||||
} else {
|
||||
EggVertex vert;
|
||||
EggVertex *vert = vpool->add_vertex(new EggVertex, i);
|
||||
LPoint4d p4d(v[0], v[1], v[2], v[3]);
|
||||
p4d = p4d * vertex_frame_inv;
|
||||
vert.set_pos(p4d);
|
||||
egg_nurbs->add_vertex(vpool->create_unique_vertex(vert));
|
||||
vert->set_pos(p4d);
|
||||
|
||||
egg_nurbs->add_vertex(vert);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1160,6 +1164,44 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
if (shader != (MayaShader *)NULL) {
|
||||
set_shader_attributes(*egg_nurbs, *shader);
|
||||
}
|
||||
|
||||
// Now try to find the skinning information for the surface.
|
||||
bool got_weights = false;
|
||||
|
||||
pvector<EggGroup *> joints;
|
||||
MFloatArray weights;
|
||||
if (_animation_convert == AC_model) {
|
||||
got_weights =
|
||||
get_vertex_weights(dag_path, surface, joints, weights);
|
||||
}
|
||||
|
||||
if (got_weights && !joints.empty()) {
|
||||
int num_joints = joints.size();
|
||||
int num_weights = (int)weights.length();
|
||||
int num_verts = num_weights / num_joints;
|
||||
// The number of weights should be an even multiple of verts *
|
||||
// joints.
|
||||
nassertv(num_weights == num_verts * num_joints);
|
||||
|
||||
for (i = 0; i < egg_nurbs->get_num_cvs(); i++) {
|
||||
int ui = egg_nurbs->get_u_index(i) % maya_u_cvs;
|
||||
int vi = egg_nurbs->get_v_index(i) % maya_v_cvs;
|
||||
|
||||
int maya_vi = maya_v_cvs * ui + vi;
|
||||
nassertv(maya_vi < num_verts);
|
||||
EggVertex *vert = vpool->get_vertex(i);
|
||||
|
||||
for (int ji = 0; ji < num_joints; ++ji) {
|
||||
float weight = weights[maya_vi * num_joints + ji];
|
||||
if (weight != 0.0f) {
|
||||
EggGroup *joint = joints[ji];
|
||||
if (joint != (EggGroup *)NULL) {
|
||||
joint->ref_vertex(vert, weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1684,6 +1726,7 @@ make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
|
||||
egg_group->add_translate(p3d);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaToEggConverter::get_vertex_weights
|
||||
// Access: Private
|
||||
@ -1776,6 +1819,100 @@ get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaToEggConverter::get_vertex_weights
|
||||
// Access: Private
|
||||
// Description: As above, for a NURBS surface instead of a polygon
|
||||
// mesh.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool MayaToEggConverter::
|
||||
get_vertex_weights(const MDagPath &dag_path, const MFnNurbsSurface &surface,
|
||||
pvector<EggGroup *> &joints, MFloatArray &weights) {
|
||||
MStatus status;
|
||||
|
||||
// Since we are working with a NURBS surface the input attribute that
|
||||
// creates the surface is named "create"
|
||||
//
|
||||
MObject attr = surface.attribute("create");
|
||||
|
||||
// Create the plug to the "create" attribute then use the
|
||||
// DG iterator to walk through the DG, at the node level.
|
||||
//
|
||||
MPlug history(surface.object(), attr);
|
||||
MItDependencyGraph it(history, MFn::kDependencyNode,
|
||||
MItDependencyGraph::kUpstream,
|
||||
MItDependencyGraph::kDepthFirst,
|
||||
MItDependencyGraph::kNodeLevel);
|
||||
|
||||
while (!it.isDone()) {
|
||||
// We will walk along the node level of the DG until we
|
||||
// spot a skinCluster node.
|
||||
//
|
||||
MObject c_node = it.thisNode();
|
||||
if (c_node.hasFn(MFn::kSkinClusterFilter)) {
|
||||
// We've found the cluster handle. Try to get the weight
|
||||
// data.
|
||||
//
|
||||
MFnSkinCluster cluster(c_node, &status);
|
||||
if (!status) {
|
||||
status.perror("MFnSkinCluster constructor");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the set of objects that influence the vertices of this
|
||||
// surface. Hopefully these will all be joints.
|
||||
MDagPathArray influence_objects;
|
||||
cluster.influenceObjects(influence_objects, &status);
|
||||
if (!status) {
|
||||
status.perror("MFnSkinCluster::influenceObjects");
|
||||
|
||||
} else {
|
||||
// Fill up the vector with the corresponding table of egg
|
||||
// groups for each joint.
|
||||
joints.clear();
|
||||
for (unsigned oi = 0; oi < influence_objects.length(); oi++) {
|
||||
MDagPath joint_dag_path = influence_objects[oi];
|
||||
MayaNodeDesc *joint_node_desc = _tree.build_node(joint_dag_path);
|
||||
EggGroup *joint = _tree.get_egg_group(joint_node_desc);
|
||||
joints.push_back(joint);
|
||||
}
|
||||
|
||||
// Now use a component object to retrieve all of the weight
|
||||
// data in one API call.
|
||||
MFnDoubleIndexedComponent dic;
|
||||
MObject dic_object = dic.create(MFn::kSurfaceCVComponent);
|
||||
dic.setCompleteData(surface.numCVsInU(), surface.numCVsInV());
|
||||
unsigned influence_count;
|
||||
|
||||
status = cluster.getWeights(dag_path, dic_object,
|
||||
weights, influence_count);
|
||||
if (!status) {
|
||||
status.perror("MFnSkinCluster::getWeights");
|
||||
} else {
|
||||
if (influence_count != influence_objects.length()) {
|
||||
mayaegg_cat.error()
|
||||
<< "MFnSkinCluster::influenceObjects() returns "
|
||||
<< influence_objects.length()
|
||||
<< " objects, but MFnSkinCluster::getWeights() reports "
|
||||
<< influence_count << " objects.\n";
|
||||
|
||||
} else {
|
||||
// We've got the weights and the set of objects. That's all
|
||||
// we need.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it.next();
|
||||
}
|
||||
|
||||
// The surface was not soft-skinned.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaShader::set_shader_attributes
|
||||
// Access: Private
|
||||
|
@ -122,6 +122,8 @@ private:
|
||||
EggGroup *egg_group);
|
||||
bool get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
|
||||
pvector<EggGroup *> &joints, MFloatArray &weights);
|
||||
bool get_vertex_weights(const MDagPath &dag_path, const MFnNurbsSurface &surface,
|
||||
pvector<EggGroup *> &joints, MFloatArray &weights);
|
||||
void set_shader_attributes(EggPrimitive &primitive,
|
||||
const MayaShader &shader);
|
||||
void apply_texture_properties(EggTexture &tex,
|
||||
|
Loading…
x
Reference in New Issue
Block a user