mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -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/MAnimUtil.h>
|
||||||
#include <maya/MFnSkinCluster.h>
|
#include <maya/MFnSkinCluster.h>
|
||||||
#include <maya/MFnSingleIndexedComponent.h>
|
#include <maya/MFnSingleIndexedComponent.h>
|
||||||
|
#include <maya/MFnDoubleIndexedComponent.h>
|
||||||
#include <maya/MItDependencyGraph.h>
|
#include <maya/MItDependencyGraph.h>
|
||||||
#include <maya/MDagPathArray.h>
|
#include <maya/MDagPathArray.h>
|
||||||
#include <maya/MSelectionList.h>
|
#include <maya/MSelectionList.h>
|
||||||
@ -1033,11 +1034,8 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
We don't use these variables currently.
|
|
||||||
MFnNurbsSurface::Form u_form = surface.formInU();
|
MFnNurbsSurface::Form u_form = surface.formInU();
|
||||||
MFnNurbsSurface::Form v_form = surface.formInV();
|
MFnNurbsSurface::Form v_form = surface.formInV();
|
||||||
*/
|
|
||||||
|
|
||||||
int u_degree = surface.degreeU();
|
int u_degree = surface.degreeU();
|
||||||
int v_degree = surface.degreeV();
|
int v_degree = surface.degreeV();
|
||||||
@ -1045,6 +1043,11 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
|||||||
int u_cvs = surface.numCVsInU();
|
int u_cvs = surface.numCVsInU();
|
||||||
int v_cvs = surface.numCVsInV();
|
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 u_knots = surface.numKnotsInU();
|
||||||
int v_knots = surface.numKnotsInV();
|
int v_knots = surface.numKnotsInV();
|
||||||
|
|
||||||
@ -1084,11 +1087,12 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
|||||||
if (!status) {
|
if (!status) {
|
||||||
status.perror("MPoint::get");
|
status.perror("MPoint::get");
|
||||||
} else {
|
} else {
|
||||||
EggVertex vert;
|
EggVertex *vert = vpool->add_vertex(new EggVertex, i);
|
||||||
LPoint4d p4d(v[0], v[1], v[2], v[3]);
|
LPoint4d p4d(v[0], v[1], v[2], v[3]);
|
||||||
p4d = p4d * vertex_frame_inv;
|
p4d = p4d * vertex_frame_inv;
|
||||||
vert.set_pos(p4d);
|
vert->set_pos(p4d);
|
||||||
egg_nurbs->add_vertex(vpool->create_unique_vertex(vert));
|
|
||||||
|
egg_nurbs->add_vertex(vert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1160,6 +1164,44 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
|||||||
if (shader != (MayaShader *)NULL) {
|
if (shader != (MayaShader *)NULL) {
|
||||||
set_shader_attributes(*egg_nurbs, *shader);
|
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);
|
egg_group->add_translate(p3d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: MayaToEggConverter::get_vertex_weights
|
// Function: MayaToEggConverter::get_vertex_weights
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -1776,6 +1819,100 @@ get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
|
|||||||
return false;
|
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
|
// Function: MayaShader::set_shader_attributes
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -122,6 +122,8 @@ private:
|
|||||||
EggGroup *egg_group);
|
EggGroup *egg_group);
|
||||||
bool get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
|
bool get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
|
||||||
pvector<EggGroup *> &joints, MFloatArray &weights);
|
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,
|
void set_shader_attributes(EggPrimitive &primitive,
|
||||||
const MayaShader &shader);
|
const MayaShader &shader);
|
||||||
void apply_texture_properties(EggTexture &tex,
|
void apply_texture_properties(EggTexture &tex,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user