示例#1
0
MStatus meshOpFty::doIt()
//
//	Description:
//		Performs the operation on the selected mesh and components
//
{
	MStatus status;
	unsigned int i, j;

	// Get access to the mesh's function set
	//
	MFnMesh meshFn(fMesh);

	// The division count argument is used in many of the operations
	// to execute the operation multiple subsequent times. For example,
	// with a division count of 2 in subdivide face, the given faces will be
	// divide once and then the resulting inner faces will be divided again.
	//
	int divisionCount = 2;

	MFloatVector translation;
	if (fOperationType == kExtrudeEdges
		|| fOperationType == kExtrudeFaces
		|| fOperationType == kDuplicateFaces
		|| fOperationType == kExtractFaces)
	{
		// The translation vector is used for the extrude, extract and 
		// duplicate operations to move the result to a new position. For 
		// example, if you extrude an edge on a mesh without a subsequent 
		// translation, the extruded edge will be on at the position of the 
		// orignal edge and the created faces will have no area.
		// 
		// Here, we provide a translation that is in the same direction as the
		// average normal of the given components.
		//
		MFn::Type componentType = getExpectedComponentType(fOperationType);
		MIntArray adjacentVertexList;
		switch (componentType)
		{
		case MFn::kMeshEdgeComponent:
			for (i = 0; i < fComponentIDs.length(); ++i)
			{
				int2 vertices;
				meshFn.getEdgeVertices(fComponentIDs[i], vertices);
				adjacentVertexList.append(vertices[0]);
				adjacentVertexList.append(vertices[1]);
			}
			break;

		case MFn::kMeshPolygonComponent:
			for (i = 0; i < fComponentIDs.length(); ++i)
			{
				MIntArray vertices;
				meshFn.getPolygonVertices(fComponentIDs[i], vertices);
				for (j = 0; j < vertices.length(); ++j)
					adjacentVertexList.append(vertices[j]);
			}
			break;
		default:	
			break;
		}
		MVector averageNormal(0, 0, 0);
		for (i = 0; i < adjacentVertexList.length(); ++i)
		{
			MVector vertexNormal;
			meshFn.getVertexNormal(adjacentVertexList[i], vertexNormal,
				MSpace::kWorld);
			averageNormal += vertexNormal;
		}
		if (averageNormal.length() < 0.001)
			averageNormal = MVector(0.0, 1.0, 0.0);
		else averageNormal.normalize();
		translation = averageNormal;
	}

	// When doing an extrude operation, there is a choice of extrude the
	// faces/edges individually or together. If extrudeTogether is true and 
	// multiple adjacent components are selected, they will be extruded as if
	// it were one more complex component.
	//
	// The following variable sets that option.
	//
	bool extrudeTogether = true;

	// Execute the requested operation
	//
	switch (fOperationType)
	{
	case kSubdivideEdges: {
		status = meshFn.subdivideEdges(fComponentIDs, divisionCount);
		CHECK_STATUS(status);
		break; }

	case kSubdivideFaces: {
		status = meshFn.subdivideFaces(fComponentIDs, divisionCount);
		CHECK_STATUS(status);
		break; }

	case kExtrudeEdges: {
		status = meshFn.extrudeEdges(fComponentIDs, divisionCount,
			&translation, extrudeTogether);
		CHECK_STATUS(status);
		break; }

	case kExtrudeFaces: {
		status = meshFn.extrudeFaces(fComponentIDs, divisionCount,
			&translation, extrudeTogether);
		CHECK_STATUS(status);
		break; }

	case kCollapseEdges: {
		status = meshFn.collapseEdges(fComponentIDs);
		CHECK_STATUS(status);
		break; }

	case kCollapseFaces: {
		status = meshFn.collapseFaces(fComponentIDs);
		CHECK_STATUS(status);
		break; }

	case kDuplicateFaces: {
		status = meshFn.duplicateFaces(fComponentIDs, &translation);
		CHECK_STATUS(status);
		break; }

	case kExtractFaces: {
		status = meshFn.extractFaces(fComponentIDs, &translation);
		CHECK_STATUS(status);
		break; }

	case kSplitLightning: {
		status = doLightningSplit(meshFn);
		CHECK_STATUS(status);
		break; }

	default:
		status = MS::kFailure;
		break;
	}

	return status;
}
示例#2
0
文件: storage.cpp 项目: ace13/openmw
    void Storage::fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center,
                                            osg::ref_ptr<osg::Vec3Array> positions,
                                            osg::ref_ptr<osg::Vec3Array> normals,
                                            osg::ref_ptr<osg::Vec4Array> colours)
    {
        // LOD level n means every 2^n-th vertex is kept
        size_t increment = 1 << lodLevel;

        osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f);
        assert(origin.x() == (int) origin.x());
        assert(origin.y() == (int) origin.y());

        int startX = static_cast<int>(origin.x());
        int startY = static_cast<int>(origin.y());

        size_t numVerts = static_cast<size_t>(size*(ESM::Land::LAND_SIZE - 1) / increment + 1);

        positions->resize(numVerts*numVerts);
        normals->resize(numVerts*numVerts);
        colours->resize(numVerts*numVerts);

        osg::Vec3f normal;
        osg::Vec4f color;

        float vertY = 0;
        float vertX = 0;

        float vertY_ = 0; // of current cell corner
        for (int cellY = startY; cellY < startY + std::ceil(size); ++cellY)
        {
            float vertX_ = 0; // of current cell corner
            for (int cellX = startX; cellX < startX + std::ceil(size); ++cellX)
            {
                ESM::Land* land = getLand(cellX, cellY);
                if (land && !(land->mDataTypes&ESM::Land::DATA_VHGT))
                    land = NULL;

                int rowStart = 0;
                int colStart = 0;
                // Skip the first row / column unless we're at a chunk edge,
                // since this row / column is already contained in a previous cell
                if (colStart == 0 && vertY_ != 0)
                    colStart += increment;
                if (rowStart == 0 && vertX_ != 0)
                    rowStart += increment;

                vertY = vertY_;
                for (int col=colStart; col<ESM::Land::LAND_SIZE; col += increment)
                {
                    vertX = vertX_;
                    for (int row=rowStart; row<ESM::Land::LAND_SIZE; row += increment)
                    {
                        float height = -2048;
                        if (land)
                            height = land->mLandData->mHeights[col*ESM::Land::LAND_SIZE + row];

                        (*positions)[static_cast<unsigned int>(vertX*numVerts + vertY)]
                            = osg::Vec3f((vertX / float(numVerts - 1) - 0.5f) * size * 8192,
                                         (vertY / float(numVerts - 1) - 0.5f) * size * 8192,
                                         height);

                        if (land && land->mDataTypes&ESM::Land::DATA_VNML)
                        {
                            normal.x() = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3];
                            normal.y() = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1];
                            normal.z() = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+2];
                            normal.normalize();
                        }
                        else
                            normal = osg::Vec3f(0,0,1);

                        // Normals apparently don't connect seamlessly between cells
                        if (col == ESM::Land::LAND_SIZE-1 || row == ESM::Land::LAND_SIZE-1)
                            fixNormal(normal, cellX, cellY, col, row);

                        // some corner normals appear to be complete garbage (z < 0)
                        if ((row == 0 || row == ESM::Land::LAND_SIZE-1) && (col == 0 || col == ESM::Land::LAND_SIZE-1))
                            averageNormal(normal, cellX, cellY, col, row);

                        assert(normal.z() > 0);

                        (*normals)[static_cast<unsigned int>(vertX*numVerts + vertY)] = normal;

                        if (land && land->mDataTypes&ESM::Land::DATA_VCLR)
                        {
                            color.r() = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f;
                            color.g() = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f;
                            color.b() = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+2] / 255.f;
                        }
                        else
                        {
                            color.r() = 1;
                            color.g() = 1;
                            color.b() = 1;
                        }

                        // Unlike normals, colors mostly connect seamlessly between cells, but not always...
                        if (col == ESM::Land::LAND_SIZE-1 || row == ESM::Land::LAND_SIZE-1)
                            fixColour(color, cellX, cellY, col, row);

                        color.a() = 1;

                        (*colours)[static_cast<unsigned int>(vertX*numVerts + vertY)] = color;

                        ++vertX;
                    }
                    ++vertY;
                }
                vertX_ = vertX;
            }
            vertY_ = vertY;

            assert(vertX_ == numVerts); // Ensure we covered whole area
        }
        assert(vertY_ == numVerts);  // Ensure we covered whole area
    }