/*!
     * \internal
     *
     * \return A new mesh object containing the mesh in \p node, or NULL if no such
     * mesh can be found.
     */
    dcollide::Shape* Loader3dsInternal::createShape(Lib3dsNode* node, Lib3dsMatrix* translateRotateMatrix) {
        if (!node) {
            return 0;
        }
        if (node->type != LIB3DS_OBJECT_NODE) {
            return 0;
        }
        if (strcmp(node->name, "$$$DUMMY") == 0) {
            // AB: nodes with this name are only transformation nodes, i.e. they
            // don't have a mesh, only a matrix.
            return 0;
        }
        Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(mFile, node->name);
        if (!mesh) {
            std::cout << "Cannot find mesh " << node->name << " in 3ds file" << std::endl;
            return 0;
        }
        if (mesh->faces < 1) {
            std::cerr << "No faces in mesh " << node->name << std::endl;
            return 0;
        }
        if (mesh->points < 3) {
            std::cerr << "Less than 3 points in mesh " << node->name << std::endl;
            return 0;
        }

        Lib3dsMatrix origMeshMatrix;
        lib3ds_matrix_copy(origMeshMatrix, mesh->matrix);
        lib3ds_matrix_inv(origMeshMatrix); // 3ds stores inverted mesh matrix
        dcollide::Matrix meshMatrix(&origMeshMatrix[0][0]);


        // AB: Ogre does not apply "scale" values to child nodes, lib3ds does.
        //     so to display the model correctly we remove the scale completely
        //     (we integrate it directly into the vertices).
        //     to do this:
        //       let M:=the lib3ds matrix the point is normally transformed by
        //              (i.e. including the parent-node matrix)
        //       let M':=the matrix d-collide will use (i.e.
        //               translation+rotation only, no scale)
        //     then for every vertex v the correct transformed position p is:
        //       Mv=p
        //     we search for a vertex v' so that:
        //       M'v'=p
        //     since we have M and v (and thus p) and M' we can do this like
        //     this:
        //       v'=(M'^-1)p
        //     which equals:
        //       v'=(M'^-1)Mv

        dcollide::Matrix nodeMatrix(&node->matrix[0][0]); // M
        Lib3dsMatrix invertedTranslateRotate3ds;
        lib3ds_matrix_copy(invertedTranslateRotate3ds, *translateRotateMatrix);
        lib3ds_matrix_inv(invertedTranslateRotate3ds);
        dcollide::Matrix invertedTranslateRotate(&invertedTranslateRotate3ds[0][0]); // M'^-1
        dcollide::Matrix removeScaleMatrix(invertedTranslateRotate);
        removeScaleMatrix.multiply(&nodeMatrix);

        Lib3dsObjectData* data = &node->data.object;
        std::vector<dcollide::Vertex*> vertices(mesh->points);
        for (unsigned int i = 0; i < mesh->points; i++) {
            Lib3dsPoint* p = &mesh->pointL[i];
            dcollide::Vector3 meshPos;
            meshMatrix.transform(&meshPos, dcollide::Vector3(
                        p->pos[0] - data->pivot[0],
                        p->pos[1] - data->pivot[1],
                        p->pos[2] - data->pivot[2]));

            dcollide::Vector3 pos;
            removeScaleMatrix.transform(&pos, meshPos);

            vertices[i] = new dcollide::Vertex(pos);
        }

        std::vector<int> indices(mesh->faces * 3);
        for (unsigned int i = 0; i < mesh->faces; i++) {
            Lib3dsFace* f = &mesh->faceL[i];
            indices[i * 3 + 0] = f->points[0];
            indices[i * 3 + 1] = f->points[1];
            indices[i * 3 + 2] = f->points[2];
        }

        dcollide::Mesh* newMesh = new dcollide::Mesh(vertices, indices);

        return newMesh;
    }
    /*!
     * See \ref Loader3ds::loadFromFileToOneMesh
     */
    dcollide::Mesh* Loader3dsInternal::loadFromFileToOneMesh(const char* fileName, TextureInformation* textureInformation) {
        // AB:
        // we cannot load texture information here, because we are merging all
        // meshes into a single one.
        // -> adjusting the texels may still be possible, however if the model
        //    uses > 1 texture, we can't change that.

        mData->mProxy2Transformation.clear();
        mData->mProxy2TextureInformation.clear();
        if (!fileName) {
            throw dcollide::NullPointerException("fileName");
        }

        mFile = lib3ds_file_load(fileName);
        if (!mFile) {
            std::cout << dc_funcinfo << "unable to load " << fileName << std::endl;
            return 0;
        }

        // AB: some files don't store nodes and just want exactly one node per mesh.
        //     atm we don't support that.
        if (!mFile->nodes) {
            std::cout << dc_funcinfo << "File " << fileName << " does not contain any nodes. mesh-only files not supported currently." << std::endl;
            lib3ds_file_free(mFile);
            mFile = 0;
            return 0;
        }

        // 3ds stores several frames, we want the first
        lib3ds_file_eval(mFile, 0);

        std::list<Lib3dsNode*> nodes;
        Lib3dsNode* node = mFile->nodes;
        while (node) {
            nodes.push_back(node);
            node = node->next;
        }

        bool texelLoadError = false;
        std::vector<dcollide::Vector3> texels;
        std::vector<dcollide::Vertex*> vertices;
        std::vector<dcollide::Triangle*> triangles;
        std::vector<int> indices;
        while (!nodes.empty()) {
            Lib3dsNode* node = nodes.front();
            nodes.pop_front();

            for (Lib3dsNode* n = node->childs; n; n = n->next) {
                nodes.push_back(n);
            }

            // node->type can be object, light, camera, ...
            // -> only object nodes are relevant to us
            if (node->type != LIB3DS_OBJECT_NODE) {
                continue;
            }

            if (strcmp(node->name, "$$$DUMMY") == 0) {
                // AB: nodes with this name are only transformation nodes, i.e. they
                // don't have a mesh, only a matrix.
                continue;
            }

            unsigned int pointOffset = vertices.size();

            Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(mFile, node->name);
            Lib3dsMatrix origMeshMatrix;
            lib3ds_matrix_copy(origMeshMatrix, mesh->matrix);
            lib3ds_matrix_inv(origMeshMatrix); // 3ds stores inverted mesh matrix
            dcollide::Matrix meshMatrix(&origMeshMatrix[0][0]);
            dcollide::Matrix nodeMatrix(&node->matrix[0][0]);

            Lib3dsObjectData* data = &node->data.object;
            nodeMatrix.translate(dcollide::Vector3(-data->pivot[0], -data->pivot[1], -data->pivot[2]));

            dcollide::Matrix matrix = nodeMatrix;
            matrix.multiply(&meshMatrix);

            for (unsigned int i = 0; i < mesh->points; i++) {
                Lib3dsPoint* p = &mesh->pointL[i];
                dcollide::Vector3 pos;
                matrix.transform(&pos, dcollide::Vector3(
                            p->pos[0],
                            p->pos[1],
                            p->pos[2]
                            ));
                vertices.push_back(new dcollide::Vertex(pos));
            }

            for (unsigned int i = 0; i < mesh->faces; i++) {
                Lib3dsFace* f = &mesh->faceL[i];
                indices.push_back(f->points[0] + pointOffset);
                indices.push_back(f->points[1] + pointOffset);
                indices.push_back(f->points[2] + pointOffset);
            }

            if (textureInformation) {
                TextureInformation t = loadTextureInformation(node);
                const std::vector<dcollide::Vector3>& nodeTexels = t.getTexels();
                if (mesh->texelL && nodeTexels.size() != mesh->texels) {
                    dcollide::warning() << "texturing problem in " << fileName;
                    dcollide::warning() << "invalid texel count loaded: have=" << nodeTexels.size() << " expected=" << mesh->texels;
                    dcollide::warning() << "adding dummy texels...";
                    for (unsigned int i = 0; i < mesh->texels; i++) {
                        texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0));
                    }
//                    texelLoadError = true;
                } else {
                    for (unsigned int i = 0; i < nodeTexels.size(); i++) {
                        texels.push_back(nodeTexels[i]);
                    }
                }
            }
        }

        if (textureInformation) {
            if (!texelLoadError) {
                textureInformation->setTextured(true);
                textureInformation->setTextureFileName("deformable.tga");
                textureInformation->setTexels(texels);
            } else {
                textureInformation->setTextured(false);
            }
        }

        lib3ds_file_free(mFile);
        mFile = 0;

        dcollide::Mesh* mesh = new dcollide::Mesh(vertices, indices);
        return mesh;
    }
示例#3
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::connectNodes( MObject modifierNode )
// --------------------------------------------------------------------------------------------
//
//	Description:
//
//		This method connects up the modifier nodes, while accounting for DG factors
//		such as construction history and tweaks. The method has a series of steps which
//		it runs through to process nodes under varying circumstances:
//
//		1) Gather meshNode connection data (ie. attributes and plugs)
//
//		2) Gather upstreamNode data - This is history-dependent. If the node has history,
//									  an actual upstreamNode exists and that is used to
//									  drive the input of our modifierNode.
//
//									  Otherwise, if the node ds not have history, the
//									  meshNode is duplicated, set as an intermediate object
//									  and regarded as our new upstreamNode which will drive
//									  the input of our modifierNode. The case with history
//									  already has this duplicate meshNode at the top, driving
//									  all other history nodes and serving as a reference
//									  to the "original state" of the node before any
//									  modifications.
//
//		3) Gather modifierNode connection data
//
//		4) Process tweak data (if it exists) - This is history-dependent. If there is
//											   history, the tweak data is extracted and deleted
//											   from the meshNode and encapsulated inside a
//											   polyTweak node. The polyTweak node is then
//											   inserted ahead of the modifier node.
//
//											   If there is no history, the same is done as
//											   in the history case, except the tweaks are
//											   deleted from the duplicate meshNode in addition
//											   to the actual meshNode.
//
//		5) Connect the nodes
//
//		6) Collapse/Bake nodes into the actual meshNode if the meshNode had no previous
//		   construction history and construction history recording is turned off.
//		   (ie. (!fHasHistory && !fHasRecordHistory) == true )
//
{
	MStatus status;

	// Declare our internal processing data structure (see polyModifierCmd.h for definition)
	//
	modifyPolyData data;	//->jetzt als ElementVariable

	// Get the mesh node, plugs and attributes
	//
	status = processMeshNode( data );
	MCheckStatus( status, "processMeshNode" );

	// Get upstream node, plugs and attributes
	//
	status = processUpstreamNode( data );
	MCheckStatus( status, "processUpstreamNode" );

	// Get the modifierNode attributes
	//
	status = processModifierNode( modifierNode,
						 data );
	MCheckStatus( status, "processModifierNode" );

	// Process tweaks on the meshNode
	//
	status = processTweaks( data );
	MCheckStatus( status, "processTweaks" );



	
	

	if( fHasTweaks )
	{

		status = fDGModifier.connect( data.upstreamNodeShape,
							 data.upstreamNodeSrcAttr,
							 data.tweakNode,
							 data.tweakNodeDestAttr );
		MCheckStatus( status, "upstream-tweak connect failed" );

		status = fDGModifier.connect( data.tweakNode,
							 data.tweakNodeSrcAttr,
							 modifierNode,
							 data.modifierNodeDestAttr );
		MCheckStatus( status, "tweak-modifier connect failed" );
	}
	else
	{
		//hier muessen die Plugs verwendet werden, weil die Attribute eventuell multis sind
		
		MPlug destPlug(modifierNode,data.modifierNodeDestAttr );
		
		INVIS(cout<<data.upstreamNodeSrcPlug.name().asChar()<<" --> "<<destPlug.name().asChar()<<endl);

		status = fDGModifier.connect( data.upstreamNodeSrcPlug,
										destPlug
									);
		MCheckStatus( status, "upstream-modifier connect failed" );
	}



	
	
	// outMesh mit inputMesh verbinden
	//
	fDGModifier.connect(MPlug(modifierNode,data.modifierNodeSrcAttr), data.meshNodeDestPlug);
	
	
	// Ausserdem das MatrixAttribut des Meshes mit dem meshMatrix Attr der Node verbinden
	//
	MFnDependencyNode depFn( modifierNode );
	MPlug	meshMatrix( modifierNode, depFn.attribute("meshMatrix") );



	depFn.setObject(data.meshNodeTransform);
	MPlug	shapeMatrix( data.meshNodeTransform, depFn.attribute("worldMatrix") );

	fDGModifier.connect(shapeMatrix.elementByLogicalIndex( 0 ), meshMatrix );


	
	

	// Jetzt die ModifierNode mit der VisNode connecten
/*	
	status = fDGModifier.connect( modifierNode,
						 data.modifierNodeSrcAttr,
						 data.meshNodeShape,
						 data.meshNodeDestAttr );
*/


//	MCheckStatus( status, "modifier-mesh connect failed" );



	status = fDGModifier.doIt();
	MCheckStatus( status, "modifier-mesh DOIT failed" );


	if(createAnimCurves)
	{
		//AnimCurve erstellen(dies ist nur hier moeglich, da die Node erst nach dem DoIt wirklich existiert (scheinbar)
		MFnAnimCurve	aCurve;

		MFnDependencyNode myDepNodeFn(modifierNode);

		aCurve.create(modifierNode,myDepNodeFn.attribute("csl"),MFnAnimCurve::kAnimCurveUU,&createSlideAnim,&status);
	}

	return status;
}